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.