sql >> Database >  >> RDS >> Database

Gegevens exporteren naar een plat bestand met BCP Utility en gegevens importeren met Bulk Insert

Met het hulpprogramma BCP (Bulk Copy Program) in SQL Server kunnen databasebeheerders gegevens importeren in een tabel en gegevens uit een tabel exporteren naar een plat bestand. Het BCP-hulpprogramma ondersteunt ook verschillende functies die het proces van het exporteren en importeren van de bulkgegevens vergemakkelijken.

Laten we nu beginnen met een zakelijk scenario.

Bedrijfsscenario

Laten we zeggen dat we een maandelijks rapport in het specifieke formaat moeten delen met een klant op een beveiligde gedeelde locatie zoals SFTS, d.w.z. aan het begin van elke maand moeten we het bestand naar een klant sturen voor de voorgaande maand. In dit scenario proberen we de opgeslagen procedure te maken om gegevens te genereren en die gegevens te exporteren naar het platte bestand (.txt of .csv).

Hoe de SQL-gegevens importeren en exporteren?

Er zijn verschillende manieren om dit te doen:

  • Gebruik SSMS, voer de query uit in het queryvenster en export of SQL Server import &export-wizard.
  • SSIS gebruiken – Een pakket maken met SSDT.
  • SSRS gebruiken.
  • C# gebruiken – Maak een console of win een applicatie om te exporteren.
  • BCP-hulpprogramma.
  • enz.

Wat is BCP-hulpprogramma?

BCP-hulpprogramma (Bulk Copy Program) is een opdrachtregelprogramma om gegevens te kopiëren tussen een exemplaar van MS SQL Server en een gegevensbestand in een door de gebruiker gespecificeerd formaat. We kunnen snel en eenvoudig grote hoeveelheden gegevens in en uit de SQL Server-databases exporteren en importeren.

Het BCP-hulpprogramma voert de volgende taken uit:

  • Bulkgegevens exporteren van een SQL Server-tabel naar een gegevensbestand.
  • Bulkgegevens exporteren vanuit een query/opgeslagen procedure.
  • Bulkgegevens importeren uit een gegevensbestand in een SQL Server-tabel.
  • Genereren van de formaatbestanden.

Meer details over BCP Utility vind je hier.

Gebruikte omgeving

  • SQL Server 2017 Developer Edition
  • SQL-server 2017 Beheerstudio
  • Wide World Importers voorbeelddatabase v1.0
  • BCP-hulpprogramma

Hoe gegevens naar een plat bestand te exporteren

Maak een opgeslagen procedure om de maandelijkse rapportgegevens te genereren.

Maak eerst de afhankelijke objecten voor de export Opgeslagen procedure.

We moeten dus de volgende tabellen maken:

  • De Orders_Monthly_Temp_Table tabel:deze tijdelijke tabel wordt gebruikt om de gegevens van de maandelijkse bestellingen op te slaan in een specifiek formaat om dat naar een tekstbestand te exporteren, d.w.z. in ons geval door alle kolommen samen te voegen tot één rij met scheidingsteken "|".
  • De Export_Config tabel:deze tabel wordt gebruikt om exportconfiguraties op te slaan, d.w.z. gedeeld mappad, plat bestandstype, scheidingsteken.

Maak een script voor Orders_Monthly_Temp_Table

CREATE TABLE [dbo].[Orders_Monthly_Temp_Table](
    [Row] [varchar](200) NOT NULL
) ON [PRIMARY]

Maak een script voor 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

Gegevens invoegen in 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

Opgeslagen procedure aanmaken en parameters

  • Hier zijn de jaar- en maandparameters optioneel.
  • Als er geen maand is opgegeven, duurt het de vorige maand en als de maand 12 is, moeten we het voorgaande jaar nemen, want als we het rapport in jan'2019 voor dec'2018 genereren.
  • Als er geen jaar is opgegeven, wordt het huidige jaar gebruikt. Het pad naar de map is verplicht.
CREATE PROCEDURE [dbo].[Orders_Monthly_Report] 
    @Month INT = NULL
    ,@Year INT = NULL
    ,@FolderPath VARCHAR(200) 
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN TRY

Parametervalidatie

--#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

Haal de configuratie op uit de exporttabel

DECLARE @ExportPath VARCHAR(200)
            ,@Delimiter CHAR(1)
            ,@FileType VARCHAR(5)

        SELECT @ExportPath = TRIM(ShareFolder)
            ,@FileType = TRIM(FileType)
            ,@Delimiter = TRIM(Delimiter)
        FROM dbo.Export_Config

De startdatum en einddatum van de maand ophalen

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

Voeg de gegevens in de tijdelijke tabel in een specifiek formaat in, d.w.z. in dit geval "| – pijpsymbool gescheiden”

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 om de gegevens naar een plat bestand te exporteren

Maak de map als deze niet bestaat met 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

Het bestand in de gedeelde map maken

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

Wijzig uw directorycontext in de map waarin BPC Utility zich bevindt

[tabel id=58 /]

De procedure uitvoeren

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

Uitvoer

Bestemmingsmap

Eigenlijk plat bestand (.txt/.cvs)

De gedeelde map moet machtigingen hebben voor het virtuele account "NT SERVICE\MSSQLSERVER"

Klik met de rechtermuisknop op het bestand of de map waarvoor u machtigingen wilt instellen → Klik op Eigenschappen → Klik op het tabblad Beveiliging. → Klik op Bewerken → Klik op Toevoegen → Typ NT SERVICE\MSSQLSERVER in het vak met de objectnaam. (klik niet op "Namen controleren" - als u op Namen controleren klikt, kan het gebeuren dat u een foutmelding krijgt 'Een object met de naam "NT SERVICE\MSSQLSERVER" kan niet worden gevonden.) → Klik op OK → kies het MSSQLSERVER-account → Voeg machtigingen toe ( Volledige controle) die nodig zijn voor het MSSQLSERVER-account:

Schakel 'xp_cmdshell' SQL Server in

EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO
EXEC sp_configure 'xp_cmdshell', 1
GO
RECONFIGURE
GO

Hoe gegevens uit een plat bestand te importeren

In dit voorbeeld gebruiken we Bulk Insert om gegevens uit het bestand te importeren. We kunnen ook Openrowset enz. gebruiken.

Maak een opgeslagen procedure om de gegevens uit een plat bestand in de gedeelde map te importeren.

Maak eerst de afhankelijke objecten voor de import Opgeslagen procedure.

We moeten dus de volgende tabellen maken

  • The Orders_Monthly tabel:deze tabel wordt gebruikt om de maandelijkse bestelgegevens uit het platte bestand op te slaan.
  • De Import_Config tafel: deze tabel wordt gebruikt om importconfiguraties op te slaan, d.w.z. pad van gedeelde map, plat bestandstype, scheidingsteken.

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

Gegevens invoegen in 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

Opgeslagen procedure aanmaken en parameters

Hetzelfde als in de export Opgeslagen procedure.

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

Parametervalidatie

Hetzelfde als in de export Opgeslagen procedure.

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

Controleer of het bestand bestaat of niet

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

De procedure uitvoeren

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

Uitvoer

Verificatie

Het proces automatiseren:

Voor het automatisch uitvoeren van het export- en importproces in een geplande tijd. laten we zeggen dat we de export op de eerste dag van de maand om 12.00 uur van de maand moeten uitvoeren voor het rapport van de laatste maand en de import later moeten uitvoeren. Dus daar moeten we de SQL Job voor maken.

Stappen om de SQL-taak te maken voor exporteren en importeren.

  • Open MS SQL Server Management Studio →
  • en u zou de "SQL Server Agent" →
  • . moeten hebben
  • Breid de "SQL Server Agent" uit in Object Explorer. →
  • Klik met de rechtermuisknop op JOB en selecteer "Nieuwe taak..." →
  • U kunt het venster "Nieuwe taak" zien en de naam ="Orders_Monthly_Export" &Beschrijving invoeren

Ga dan naar het tabblad Stappen → Klik op Nieuwe knop onderaan → er wordt een nieuw venster Taakstappen geopend → Voer de naam in ="execute [Exp_Orders_Monthly_Report] SP" en Type ="Transact-SQL-script (T-SQL)" → Plak het volgende script in het gebied Opdrachttekst en klik op 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

Ga dan naar het tabblad Schema → Klik onderaan op Nieuwe knop → een nieuw taakschema wordt geopend. Voer de naam in ="Maandelijkse bestelling bestellen" en voer de volgende details in en klik op OK → Klik nogmaals op OK in het venster Nieuwe taak.

De taak zou met succes worden aangemaakt.

Test de SQL-taak:

Verwijder alle bestanden in de gedeelde map om te testen.

Om de taak handmatig uit te voeren om te testen:Klik met de rechtermuisknop op de nieuw gemaakte taak → Klik op 'Start taak bij stap..' en we kunnen zien dat de taak wordt uitgevoerd

We kunnen zien dat het bestand is aangemaakt in de gedeelde map.

Opmerking:volg de bovenstaande stappen om ook de SQL-taak (Orders_Monthly_Import) voor importeren te maken.

Ik hoop dat je nu een beter begrip hebt van het gebruik van het BCP-hulpprogramma.

Handig hulpmiddel:

dbForge Data Pump – een SSMS-invoegtoepassing voor het vullen van SQL-databases met externe brongegevens en het migreren van gegevens tussen systemen.


  1. SQLite BESTAAT

  2. SQL Server SP - Passparameter voor IN-arraylijst?

  3. Hoe krijg ik een bestand van BLOB in Oracle?

  4. Hoe ATAN2() werkt in MariaDB