Database
 sql >> Datenbank >  >> RDS >> Database

So exportieren Sie Daten mit dem BCP-Dienstprogramm in eine Flatfile und importieren Daten mit Bulk Insert

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.