Narzędzie BCP (Bulk Copy Program) w SQL Server umożliwia administratorom baz danych importowanie danych do tabeli i eksportowanie danych z tabeli do zwykłego pliku. Narzędzie BCP obsługuje również różne funkcje, które ułatwiają proces eksportowania i importowania danych zbiorczych.
Teraz zacznijmy od scenariusza biznesowego.
Scenariusz biznesowy
Załóżmy, że musimy udostępnić klientowi miesięczny raport w określonym formacie w zabezpieczonej udostępnionej lokalizacji, takiej jak SFTS, tj. na początku każdego miesiąca musimy wysłać klientowi plik za poprzedni miesiąc. W tym scenariuszu spróbujemy utworzyć procedurę składowaną w celu wygenerowania danych i wyeksportowania tych danych do zwykłego pliku (.txt lub .csv).
Jak importować i eksportować dane SQL?
Można to zrobić na kilka sposobów:
- Używając SSMS, uruchom zapytanie w oknie zapytania i eksportuj lub kreatora importu i eksportu SQL Server.
- Korzystanie z SSIS – tworzenie pakietu przy użyciu SSDT.
- Korzystanie z usług SSRS.
- Korzystanie z C# – Utwórz konsolę lub wygraj aplikację do wyeksportowania.
- Narzędzie BCP.
- itd.
Co to jest narzędzie BCP?
Narzędzie BCP (program do kopiowania zbiorczego) to narzędzie wiersza poleceń do kopiowania danych między instancją MS SQL Server a plikiem danych w formacie określonym przez użytkownika. Możemy szybko i łatwo eksportować i importować duże ilości danych do i z baz danych SQL Server.
Narzędzie BCP wykonuje następujące zadania:
- Zbiorczy eksport danych z tabeli SQL Server do pliku danych.
- Zbiorczy eksport danych z zapytania/procedury przechowywanej.
- Zbiorczy import danych z pliku danych do tabeli SQL Server.
- Generowanie plików formatu.
Więcej informacji na temat narzędzia BCP można znaleźć tutaj.
Wykorzystane środowisko
- SQL Server 2017 Developer Edition
- SQL Server 2017 Studio zarządzania
- Przykładowa baza danych Importerów z całego świata v1.0
- Narzędzie BCP
Jak wyeksportować dane do pliku płaskiego
Utwórz procedurę składowaną, aby wygenerować miesięczne dane raportu.
Najpierw utwórz obiekty zależne dla procedury zapisanej eksportu.
Musimy więc stworzyć następujące tabele:
- Tabela_zamówień_miesięcznych_temperaturowych table:ta tymczasowa tabela służy do przechowywania miesięcznych danych zamówień w określonym formacie w celu wyeksportowania ich do pliku tekstowego, tj. w naszym przypadku łączenia wszystkich kolumn w jeden wiersz z ogranicznikiem „|”.
- Eksportuj_konfigurację table:ta tabela służy do przechowywania konfiguracji eksportu, tj. ścieżki folderu współdzielonego, typu pliku płaskiego, ogranicznika.
Utwórz skrypt dla Orders_Monthly_Temp_Table

CREATE TABLE [dbo].[Orders_Monthly_Temp_Table](
[Row] [varchar](200) NOT NULL
) ON [PRIMARY] Utwórz skrypt dla Export_Config

CREATE TABLE [dbo].[Export_Config](
[Exp_Id] [int] IDENTITY(1,1) NOT NULL,
[ShareFolder] [varchar](200) NOT NULL,
[FileType] [varchar](5) NOT NULL,
[Delimiter] [char](1) NOT NULL,
CONSTRAINT [PK_Export_Config] PRIMARY KEY CLUSTERED
(
[Exp_Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [USERDATA]
) ON [USERDATA]
GO Wstaw dane do Export_Config

SET IDENTITY_INSERT [dbo].[Export_Config] ON GO INSERT [dbo].[Export_Config] ([Exp_Id], [ShareFolder], [FileType], [Delimiter]) VALUES (1, N'\\AASHREEPC\FileServer\OrdersMonthly', N'.txt', N'|') GO SET IDENTITY_INSERT [dbo].[Export_Config] OFF GO
Tworzenie i parametry procedury składowanej
- Tutaj parametry roku i miesiąca są opcjonalne.
- Jeśli miesiąc nie jest określony, zajmuje on poprzedni miesiąc, a jeśli miesiąc to 12, musimy wziąć poprzedni rok, ponieważ jeśli generujemy raport w styczniu 2019 r. za grudzień 2018 r.
- Jeśli nie określono roku, przyjmuje się rok bieżący, a ścieżka folderu jest obowiązkowa.
CREATE PROCEDURE [dbo].[Orders_Monthly_Report]
@Month INT = NULL
,@Year INT = NULL
,@FolderPath VARCHAR(200)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY Weryfikacja parametrów
--#region Parametes validation
IF NULLIF(@Month, '') IS NULL
BEGIN
SELECT @Month = DATEPART(mm, DATEADD(month, - 1, GETDATE()))
IF (@Month = 12) –
BEGIN
SELECT @Year = DATEPART(Year, GETDATE()) - 1
END
END
IF NULLIF(@Year, '') IS NULL
BEGIN
SELECT @Year = DATEPART(Year, GETDATE())
END
IF NULLIF(@FolderPath, '') IS NULL
BEGIN
--SELECT @FolderPath = '\\AASHREEPC\FileServer'
SELECT 'ERROR FolderPath must be specified.'
RETURN;
END
--#endregion Parameters validation Pobierz konfigurację z tabeli eksportu
DECLARE @ExportPath VARCHAR(200)
,@Delimiter CHAR(1)
,@FileType VARCHAR(5)
SELECT @ExportPath = TRIM(ShareFolder)
,@FileType = TRIM(FileType)
,@Delimiter = TRIM(Delimiter)
FROM dbo.Export_Config Pobieranie daty rozpoczęcia i zakończenia miesiąca
DECLARE @MonthStartDate DATETIME = DATEADD(month, @Month - 1, DATEADD(year, @Year - 1900, 0))
,@MonthEndDate DATETIME = DATEADD(day, - 1, DATEADD(month, @Month, DATEADD(year, @Year - 1900, 0)))
Check and Create the temporary table for report data/result
IF NOT EXISTS (
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[Orders_Monthly_Temp_Table]')
AND type IN (N'U')
)
BEGIN
CREATE TABLE [dbo].Orders_Monthly_Temp_Table ([Row] [varchar](200) NOT NULL) ON [PRIMARY]
END Wstaw dane do tabeli tymczasowej w określonym formacie, tj. w tym przypadku „| – symbol rury oddzielony”
TRUNCATE TABLE Orders_Monthly_Temp_Table
INSERT INTO Orders_Monthly_Temp_Table
SELECT CAST([OrderID] AS VARCHAR(10)) + ' | ' + CAST(c.[CustomerName] AS VARCHAR(50)) + ' | ' + CAST(p.[FullName] AS VARCHAR(50)) + ' | ' + ISNULL(CAST([PickedByPersonID] AS VARCHAR(4)), '') + ' | ' + CAST(p.[FullName] AS VARCHAR(20)) + ' | ' + ISNULL(CAST([BackorderOrderID] AS VARCHAR(4)), '') + ' | ' + CAST([OrderDate] AS VARCHAR(20)) + ' | ' + CAST([ExpectedDeliveryDate] AS VARCHAR(20)) + ' | ' + CAST([CustomerPurchaseOrderNumber] AS VARCHAR(10)) + ' | ' + CAST([IsUndersupplyBackordered] AS VARCHAR(4)) + ' | ' + ISNULL(CAST([Comments] AS VARCHAR(50)), '') + ' | ' + ISNULL(CAST([DeliveryInstructions] AS VARCHAR(50)), '') + ' | ' + ISNULL(CAST([InternalComments] AS VARCHAR(50)), '') + ' | ' + CAST([PickingCompletedWhen] AS VARCHAR(20)) + ' | ' + CAST(o.[LastEditedBy] AS VARCHAR(4)) + ' | ' + CAST([LastEditedWhen] AS VARCHAR(20)) AS Row
FROM [WideWorldImporters].[Sales].[Orders] o
INNER JOIN [Sales].[Customers] c ON o.[CustomerID] = c.[CustomerID]
INNER JOIN [Application].[People] p ON o.[SalespersonPersonID] = p.[PersonID]
WHERE OrderDate BETWEEN @MonthStartDate
AND @MonthEndDate Kod eksportu danych do pliku płaskiego
Utwórz folder, jeśli nie istnieje, używając SQL xp_create_subdir
DECLARE @sql VARCHAR(8000)
,@FilePath VARCHAR(200)
,@Query VARCHAR(100)
DECLARE @file_results TABLE (
file_exists INT
,file_is_a_directory INT
,parent_directory_exists INT
)
SET @FolderPath = @FolderPath + '\' + CAST(@Year AS VARCHAR(10)) + '\' + CAST(@Month AS VARCHAR(10)) + '\'
INSERT INTO @file_results
EXEC MASTER.dbo.xp_fileexist @FolderPath
IF NOT EXISTS (
SELECT 1
FROM @file_results
WHERE file_is_a_directory = 1
)
EXEC MASTER.dbo.xp_create_subdir @FolderPath Tworzenie pliku w udostępnionym folderze
SET @FilePath = '"' + @FolderPath + '' + 'Orders_Monthly' + '_' + (
SELECT Format(GETDATE(), N'yyyyMMddHHmmss')
) + '.txt"'
SET @Query = '"SELECT * from ' + (
SELECT DB_NAME()
) + '.dbo.Orders_Monthly_Temp_Table"'
DECLARE @exe_path10 VARCHAR(200) = ' cd C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\130 & '
SELECT @sql = @exe_path10 + ' bcp.exe ' + @Query + ' queryout ' + @FilePath + ' -T -c -q -t0x7c -r\n ' --+ @@servername
EXEC master..xp_cmdshell @sql
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber
,ERROR_STATE() AS ErrorState
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH
SET NOCOUNT OFF;
END
Zmień kontekst katalogu na folder, w którym znajduje się narzędzie BPC
[identyfikator tabeli=58 /]
Wykonywanie procedury
DECLARE @return_value int
EXEC @return_value = [dbo].[Exp_Orders_Monthly_Report]
@Month = NULL,
@Year = NULL,
@FolderPath = NULL
SELECT 'Return Value' = @return_value
GO Wyjście

Folder docelowy

Rzeczywisty plik płaski (.txt/.cvs)

Udostępniony folder powinien mieć uprawnienia do konta wirtualnego „NT SERVICE\MSSQLSERVER”
Kliknij prawym przyciskiem myszy plik lub folder, dla którego chcesz ustawić uprawnienia → Kliknij Właściwości → Kliknij kartę Zabezpieczenia. → Kliknij Edytuj → Kliknij Dodaj → Wpisz NT SERVICE\MSSQLSERVER w polu nazwy obiektu. (nie klikaj „Sprawdź nazwy” – jeśli klikniesz Sprawdź nazwy może się zdarzyć, że pojawi się błąd „Nie można znaleźć obiektu o nazwie „NT SERVICE\MSSQLSERVER”.) → Kliknij OK → wybierz konto MSSQLSERVER → Dodaj uprawnienia ( Pełna kontrola), które są potrzebne do konta MSSQLSERVER:

Włącz serwer SQL „xp_cmdshell”
EXEC sp_configure 'show advanced options', 1 GO RECONFIGURE GO EXEC sp_configure 'xp_cmdshell', 1 GO RECONFIGURE GO
Jak importować dane z pliku płaskiego
W tym przykładzie używamy Wstaw zbiorczy do importowania danych z pliku. Możemy również użyć Openrowset itp.
Utwórz procedurę składowaną, aby zaimportować dane z pliku płaskiego w folderze Udostępnionym.
Najpierw utwórz obiekty zależne dla procedury przechowywanej importu.
Musimy więc stworzyć następujące tabele
- Zamówienia_Miesięczne table:ta tabela służy do przechowywania miesięcznych danych zamówień z pliku płaskiego.
- Karta Importuj_konfigurację tabela: ta tabela służy do przechowywania konfiguracji importu, tj. ścieżki folderu współdzielonego, typu pliku płaskiego, ogranicznika.

CREATE TABLE [dbo].[Orders_Monthly](
[OrderID] [int] NOT NULL,
[CustomerName] [varchar](50) NOT NULL,
[SalespersonPersonName] [varchar](50) NOT NULL,
[PickedByPersonName] [varchar](50) NULL,
[ContactPersonName] [varchar](50) NOT NULL,
[BackorderOrderID] [varchar](4) NULL,
[OrderDate] [date] NOT NULL,
[ExpectedDeliveryDate] [date] NOT NULL,
[CustomerPurchaseOrderNumber] [nvarchar](20) NULL,
[IsUndersupplyBackordered] [bit] NOT NULL,
[Comments] [nvarchar](max) NULL,
[DeliveryInstructions] [nvarchar](max) NULL,
[InternalComments] [nvarchar](max) NULL,
[PickingCompletedWhen] [datetime2](7) NULL,
[LastEditedBy] [int] NOT NULL,
[LastEditedWhen] [datetime2](7) NOT NULL,
CONSTRAINT [PK_Orders_Monthly] PRIMARY KEY CLUSTERED
(
[OrderID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [USERDATA]
) ON [USERDATA] TEXTIMAGE_ON [USERDATA]
GO

CREATE TABLE [dbo].[Import_Config](
[Exp_Id] [int] IDENTITY(1,1) NOT NULL,
[ShareFolder] [nchar](200) NOT NULL,
[FileType] [varchar](5) NOT NULL,
[Delimiter] [char](1) NOT NULL
) ON [USERDATA]
GO Wstaw dane do Import_Config

SET IDENTITY_INSERT [dbo].[Import_Config] ON GO INSERT [dbo].[Import_Config] ([Exp_Id], [ShareFolder], [FileType], [Delimiter]) VALUES (1, N'\\AASHREEPC\FileServer\OrdersMonthly', N'.txt', N'|') GO SET IDENTITY_INSERT [dbo].[Import_Config] OFF GO
Tworzenie i parametry procedury składowanej
Tak samo jak w przypadku procedury przechowywanej eksportu.
CREATE PROCEDURE [dbo].[Imp_Orders_Monthly_Report] @Month INT = NULL
,@Year INT = NULL
,@FolderPath VARCHAR(200) = NULL
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
Get the configuration from the import table
DECLARE @ImportPath VARCHAR(200)
,@Delimiter CHAR(1)
,@FileType VARCHAR(5)
,@FilePath VARCHAR(200)
SELECT @ImportPath = TRIM(ShareFolder)
,@FileType = TRIM(FileType)
,@Delimiter = TRIM(Delimiter)
FROM dbo.Import_Config Weryfikacja parametrów
Tak samo jak w przypadku procedury przechowywanej eksportu.
SET @FolderPath = @ImportPath + '\' + CAST(@Year AS VARCHAR(10)) + '\' + CAST(@Month AS VARCHAR(10)) + '\'
END
ELSE
BEGIN
--SELECT @FolderPath = '\\AASHREEPC\FileServer\OrdersMonthly'
SELECT 'ERROR FolderPath must be specified.'
RETURN;
END
END
--#endregion Parametes validation Sprawdź, czy plik istnieje, czy nie
CREATE TABLE #File (
FileName SYSNAME
,Depth TINYINT
,IsFile TINYINT
);
INSERT INTO #File (
FileName
,Depth
,IsFile
)
EXEC xp_DirTree @FolderPath
,1
,1
SELECT TOP 1 @FilePath = @FolderPath + '\' + FileName
FROM #File
ORDER BY FileName DESC;
IF NULLIF((SELECT TOP 1 FileName FROM #File ORDER BY FileName DESC), '') IS NULL
BEGIN
SELECT 'ERROR import File does not exists'
RETURN;
END
DROP TABLE #File
Import the data from the shared folder using Bulk Insert
DECLARE @SQL_BULK VARCHAR(MAX)
DecLare @Errorlog varchar (Max) = @FolderPath + '\Error.log'
SET @SQL_BULK = 'BULK
INSERT [Orders_Monthly]
FROM ''' + @FilePath + '''
WITH
(
DATAFILETYPE = ''char''
,BATCHSIZE = 50000
,CODEPAGE = ''RAW''
,FIRSTROW = 1
,FIELDTERMINATOR = '''example@sqldat.com+'''
,ROWTERMINATOR = ''\n''
,KEEPNULLS
,ERRORFILE = '''+ @Errorlog + '''
,MAXERRORS = 20000
,TABLOCK
)'
EXEC (@SQL_BULK)
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber
,ERROR_STATE() AS ErrorState
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH
SET NOCOUNT OFF;
END Wykonywanie procedury

DECLARE @return_value int
EXEC @return_value = [dbo].[Imp_Orders_Monthly_Report]
@Month = NULL,
@Year = NULL,
@FolderPath = NULL
SELECT 'Return Value' = @return_value
GO Wyjście

Weryfikacja


Automatyzacja procesu:
Do automatycznego uruchamiania procesu eksportu i importu w zaplanowanym czasie. powiedzmy, że musimy uruchomić eksport pierwszego dnia miesiąca o godzinie 12:00 miesiąca dla raportu z ostatniego miesiąca, a import uruchomić później. W tym celu musimy stworzyć zadanie SQL.
Kroki tworzenia zadania SQL do eksportu i importu.
- Otwórz MS SQL Server Management Studio →
- i powinieneś mieć „SQL Server Agent” →
- Rozwiń „SQL Server Agent” w Eksploratorze obiektów. →
- Kliknij prawym przyciskiem myszy ZADANIE i wybierz „Nowe zadanie…” →
- Możesz zobaczyć okno „Nowa oferta pracy” i wprowadzić nazwę =„Orders_Monthly_Export” &opis

Następnie przejdź do zakładki Steps → Kliknij New Button na dole → otworzy się nowe okno Job Steps → Wpisz Name =„wykonaj [Exp_Orders_Monthly_Report] SP” i wpisz =„Transact-SQL Script (T-SQL)” → Wklej następujący skrypt w polu tekstowym polecenia i kliknij OK.
USE [WideWorldImporters]
GO
DECLARE @return_value int+
EXEC @return_value = [dbo].[Exp_Orders_Monthly_Report]
@Month = NULL,
@Year = NULL,
@FolderPath = NULL
SELECT 'Return Value' = @return_value
GO

Następnie przejdź do zakładki Harmonogram → Kliknij przycisk Nowy na dole → otworzy się okno Harmonogram nowego zadania. Wprowadź Nazwę =„Zamów Miesięczny Harmonogram” i wprowadź następujące dane, a następnie kliknij OK → Ponownie kliknij OK w oknie Nowa praca.
Praca zostanie pomyślnie utworzona.


Przetestuj zadanie SQL:
Usuń wszystkie pliki w folderze Shared do testowania.

Aby ręcznie uruchomić zadanie w celu przetestowania:Kliknij prawym przyciskiem myszy Nowo utworzone zadanie → Kliknij „Rozpocznij zadanie w kroku…” i zobaczymy uruchomione zadanie


Widzimy, że plik jest tworzony w folderze Shared.

Uwaga:Postępuj zgodnie z powyższymi krokami, aby utworzyć zadanie SQL (Orders_Monthly_Import) również do importu.
Mam nadzieję, że teraz lepiej rozumiesz, jak korzystać z narzędzia BCP.
Przydatne narzędzie:
dbForge Data Pump – dodatek SSMS do wypełniania baz danych SQL zewnętrznymi danymi źródłowymi i migracji danych między systemami.