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 = '''[email protected]+''' ,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.