Das Dienstprogramm BCP (Bulk Copy Program) in SQL Server ermöglicht es Datenbankadministratoren, Daten in eine Tabelle zu importieren und Daten aus einer Tabelle in eine Flatfile zu exportieren. Das BCP-Dienstprogramm unterstützt auch verschiedene Funktionen, die den Prozess des Exportierens und Importierens von Massendaten erleichtern.
Beginnen wir nun mit einem Geschäftsszenario.
Geschäftsszenario
Nehmen wir an, wir müssen einen monatlichen Bericht im bestimmten Format an einen Kunden an einem gesicherten gemeinsam genutzten Ort wie SFTS weitergeben, d. h. zu Beginn jedes Monats müssen wir die Datei für den Vormonat an einen Kunden senden. In diesem Szenario versuchen wir, die gespeicherte Prozedur zum Generieren von Daten zu erstellen und diese Daten in die Flatfile (.txt oder .csv) zu exportieren.
Wie importiere und exportiere ich die SQL-Daten?
Dafür gibt es mehrere Möglichkeiten:
- Führen Sie mit SSMS die Abfrage im Abfragefenster aus und exportieren Sie sie oder den Import- und Exportassistenten von SQL Server.
- Using SSIS – Erstellen eines Pakets mit SSDT.
- Mit SSRS.
- C# verwenden – Konsole erstellen oder Win-Anwendung zum Exportieren erstellen.
- BCP-Dienstprogramm.
- usw.
Was ist das BCP-Dienstprogramm?
Das Dienstprogramm BCP (Bulk Copy Program) ist ein Befehlszeilenprogramm zum Kopieren von Daten zwischen einer Instanz von MS SQL Server und einer Datendatei in einem benutzerdefinierten Format. Wir können große Datenmengen schnell und einfach in und aus den SQL Server-Datenbanken exportieren und importieren.
Das BCP-Dienstprogramm führt die folgenden Aufgaben aus:
- Massendatenexport aus einer SQL Server-Tabelle in eine Datendatei.
- Massendatenexport aus einer Abfrage/gespeicherten Prozedur.
- Massendatenimport aus einer Datendatei in eine SQL Server-Tabelle.
- Generierung der Formatdateien.
Weitere Einzelheiten zum BCP-Dienstprogramm finden Sie hier.
Verwendete Umgebung
- SQL Server 2017 Developer Edition
- SQL Server 2017 Management Studio
- Wide World Importers Beispieldatenbank v1.0
- BCP-Dienstprogramm
So exportieren Sie Daten in eine Flatfile
Erstellen Sie eine gespeicherte Prozedur, um die monatlichen Berichtsdaten zu generieren.
Erstellen Sie zunächst die abhängigen Objekte für die gespeicherte Exportprozedur.
Also müssen wir die folgenden Tabellen erstellen:
- DieOrders_Monthly_Temp_Table Tabelle:Diese temporäre Tabelle wird verwendet, um die monatlichen Bestelldaten in einem bestimmten Format zu speichern, um sie in eine Textdatei zu exportieren, d. h. in unserem Fall werden alle Spalten in einer Zeile mit dem Trennzeichen „|“ verkettet.
- Die Export_Config Tabelle:Diese Tabelle wird verwendet, um Exportkonfigurationen zu speichern, d. h. Pfad des freigegebenen Ordners, Flat-File-Typ, Trennzeichen.
Erstellen Sie ein Skript für Orders_Monthly_Temp_Table
CREATE TABLE [dbo].[Orders_Monthly_Temp_Table]( [Row] [varchar](200) NOT NULL ) ON [PRIMARY]
Erstellen Sie ein Skript für 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
Daten in Export_Config einfügen
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
Erstellung und Parameter gespeicherter Prozeduren
- Hier sind die Jahres- und Monatsparameter optional.
- Wenn kein Monat angegeben ist, wird der Vormonat genommen, und wenn der Monat 12 ist, müssen wir das Vorjahr nehmen, denn wenn wir den Bericht im Januar 2019 für Dezember 2018 erstellen.
- Wenn kein Jahr angegeben ist, wird das aktuelle Jahr verwendet. Der Ordnerpfad ist obligatorisch.
CREATE PROCEDURE [dbo].[Orders_Monthly_Report] @Month INT = NULL ,@Year INT = NULL ,@FolderPath VARCHAR(200) AS BEGIN SET NOCOUNT ON; BEGIN TRY
Parametervalidierung
--#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
Holen Sie die Konfiguration aus der Exporttabelle
DECLARE @ExportPath VARCHAR(200) ,@Delimiter CHAR(1) ,@FileType VARCHAR(5) SELECT @ExportPath = TRIM(ShareFolder) ,@FileType = TRIM(FileType) ,@Delimiter = TRIM(Delimiter) FROM dbo.Export_Config
Startdatum und Enddatum des Monats abrufen
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
Fügen Sie die Daten in einem bestimmten Format in die temporäre Tabelle ein, d. h. in diesem Fall „| – Pipe-Symbol getrennt“
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
Code zum Exportieren der Daten in eine Flatfile
Erstellen Sie den Ordner, falls er nicht existiert, mit 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
Erstellen der Datei im freigegebenen Ordner
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
Ändern Sie Ihren Verzeichniskontext in den Ordner, in dem sich BPC Utility befindet
[Tabellen-ID=58 /]
Vorgang ausführen
DECLARE @return_value int EXEC @return_value = [dbo].[Exp_Orders_Monthly_Report] @Month = NULL, @Year = NULL, @FolderPath = NULL SELECT 'Return Value' = @return_value GO
Ausgabe
Zielordner
Eigentliche Flatfile (.txt/.cvs)
Der freigegebene Ordner sollte Berechtigungen für das virtuelle Konto „NT SERVICE\MSSQLSERVER“ haben
Klicken Sie mit der rechten Maustaste auf die Datei oder den Ordner, für die bzw. den Sie Berechtigungen festlegen möchten → Klicken Sie auf Eigenschaften → Klicken Sie auf die Registerkarte Sicherheit. → Klicken Sie auf Bearbeiten. → Klicken Sie auf Hinzufügen. → Geben Sie NT SERVICE\MSSQLSERVER in das Feld Objektname ein. (Klicken Sie nicht auf „Namen prüfen“ – wenn Sie auf Namen prüfen klicken, kann es passieren, dass Sie eine Fehlermeldung erhalten:„Ein Objekt mit dem Namen „NT SERVICE\MSSQLSERVER“ kann nicht gefunden werden.) → Klicken Sie auf OK → Wählen Sie das MSSQLSERVER-Konto aus → Berechtigungen hinzufügen ( Vollzugriff), die für das MSSQLSERVER-Konto benötigt werden:
Aktivieren Sie den SQL-Server „xp_cmdshell“
EXEC sp_configure 'show advanced options', 1 GO RECONFIGURE GO EXEC sp_configure 'xp_cmdshell', 1 GO RECONFIGURE GO
So importieren Sie Daten aus Flatfiles
In diesem Beispiel verwenden wir Bulk Insert, um Daten aus der Datei zu importieren. Wir können auch Openrowset usw. verwenden.
Erstellen Sie eine gespeicherte Prozedur, um die Daten aus einer Flatfile im freigegebenen Ordner zu importieren.
Erstellen Sie zuerst die abhängigen Objekte für die gespeicherte Importprozedur.
Also müssen wir die folgenden Tabellen erstellen
- Die Orders_Monthly Tabelle:In dieser Tabelle werden die monatlichen Bestelldaten aus der Flatfile gespeichert.
- Die Import_Config Tabelle: Diese Tabelle wird verwendet, um Importkonfigurationen zu speichern, d. h. den Pfad des freigegebenen Ordners, den Flat-File-Typ und das Trennzeichen.
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
Daten in Import_Config einfügen
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
Erstellung und Parameter gespeicherter Prozeduren
Dasselbe wie in der gespeicherten Exportprozedur.
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
Parametervalidierung
Dasselbe wie in der gespeicherten Exportprozedur.
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
Überprüfen Sie, ob die Datei existiert oder nicht
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
Vorgang ausführen
DECLARE @return_value int EXEC @return_value = [dbo].[Imp_Orders_Monthly_Report] @Month = NULL, @Year = NULL, @FolderPath = NULL SELECT 'Return Value' = @return_value GO
Ausgabe
Verifizierung
Automatisierung des Prozesses:
Zum automatischen Ausführen des Export- und Importvorgangs zu einem geplanten Zeitpunkt. Angenommen, wir müssen den Export am ersten Tag des Monats um 00:00 Uhr des Monats für den Bericht des letzten Monats ausführen und den Import später ausführen. Dafür müssen wir also den SQL-Job erstellen.
Schritte zum Erstellen des SQL-Jobs für den Export und Import.
- Öffnen Sie MS SQL Server Management Studio →
- und Sie sollten den „SQL Server Agent“ haben →
- Erweitern Sie den „SQL Server Agent“ im Objekt-Explorer. →
- Klicken Sie mit der rechten Maustaste auf JOB und wählen Sie „Neuer Job…“ →
- Sie können das Fenster „Neuer Job“ sehen und den Namen =„Orders_Monthly_Export“ &Description eingeben
Gehen Sie dann zur Registerkarte „Schritte“ → Klicken Sie unten auf „Neue Schaltfläche“ → Ein neues Fenster „Auftragsschritte“ wird geöffnet → Geben Sie den Namen „execute [Exp_Orders_Monthly_Report] SP“ und den Typ „=„Transact-SQL Script (T-SQL)““ ein → Fügen Sie das folgende Skript ein in den Befehlstextbereich und klicken Sie auf 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
Gehen Sie dann zur Registerkarte Zeitplan → Klicken Sie unten auf die Schaltfläche Neu → ein neues Job-Zeitplan-Fenster wird geöffnet. Geben Sie den Namen =„Monatsplan bestellen“ und die folgenden Details ein und klicken Sie auf „OK“ → Klicken Sie im Fenster „Neuer Job“ erneut auf „OK“.
Der Job wurde erfolgreich erstellt.
Testen Sie den SQL-Job:
Löschen Sie zum Testen alle Dateien im freigegebenen Ordner.
So führen Sie den Job zu Testzwecken manuell aus:Klicken Sie mit der rechten Maustaste auf den neu erstellten Job → Klicken Sie auf „Start Job at step..“ und wir können sehen, dass der Job ausgeführt wird
Wir können sehen, dass die Datei im freigegebenen Ordner erstellt wurde.
Hinweis:Bitte befolgen Sie die obigen Schritte, um den SQL-Job (Orders_Monthly_Import) auch für den Import zu erstellen.
Ich hoffe, dass Sie jetzt ein besseres Verständnis für die Verwendung des BCP-Dienstprogramms haben.
Nützliches Tool:
dbForge Data Pump – ein SSMS-Add-In zum Füllen von SQL-Datenbanken mit externen Quelldaten und zum Migrieren von Daten zwischen Systemen.