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 = '''example@sqldat.com+'''
,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.