L'utilità BCP (Bulk Copy Program) in SQL Server consente agli amministratori di database di importare dati in una tabella ed esportare dati da una tabella in un file flat. L'utilità BCP supporta anche varie funzionalità che facilitano il processo di esportazione e importazione dei dati in blocco.
Ora iniziamo con uno scenario aziendale.
Scenario aziendale
Diciamo che dobbiamo condividere un report mensile nel formato specifico a un cliente in una posizione condivisa protetta come SFTS, ovvero all'inizio di ogni mese, dobbiamo inviare il file a un cliente per il mese precedente. In questo scenario, proveremo a creare la stored procedure per generare dati ed esportarli nel file flat (.txt o .csv).
Come importare ed esportare i dati SQL?
Esistono diversi modi per farlo:
- Utilizzando SSMS, esegui la query nella finestra della query ed esporta o importa e esporta la procedura guidata di SQL Server.
- Utilizzo di SSIS:creazione di un pacchetto tramite SSDT.
- Utilizzo di SSRS.
- Utilizzo di C#:crea una console o vinci un'applicazione da esportare.
- Utilità BCP.
- ecc.
Cos'è l'utilità BCP?
L'utilità BCP (programma di copia in blocco) è un'utilità della riga di comando per copiare i dati tra un'istanza di MS SQL Server e un file di dati in un formato specificato dall'utente. Possiamo esportare e importare grandi quantità di dati dentro e fuori i database di SQL Server in modo rapido e semplice.
L'utilità BCP esegue le seguenti attività:
- Esportazione in blocco di dati da una tabella di SQL Server in un file di dati.
- Esportazione in blocco di dati da una query/Stored procedure.
- Importazione in blocco di dati da un file di dati in una tabella di SQL Server.
- Generazione dei file di formato.
Puoi trovare maggiori dettagli sull'utilità BCP qui.
Ambiente utilizzato
- Edizione per sviluppatori SQL Server 2017
- Studio di gestione di SQL Server 2017
- Banca dati di esempio di Wide World Importers v1.0
- Utilità BCP
Come esportare i dati in un file flat
Crea una stored procedure per generare i dati del report mensile.
Innanzitutto, crea gli oggetti dipendenti per la stored procedure di esportazione.
Quindi dobbiamo creare le seguenti tabelle:
- La Tabella_Tempo_Mensile_Ordini tabella:questa tabella temporanea serve per memorizzare i dati degli ordini mensili in un formato specifico per esportarli in file di testo ovvero nel nostro caso concatenando tutte le colonne in una riga con delimitatore “|”.
- La Configura_Esporta tabella:questa tabella viene utilizzata per memorizzare le configurazioni di esportazione, ovvero il percorso della cartella condivisa, il tipo di file flat, il delimitatore.
Crea uno script per Orders_Monthly_Temp_Table

CREATE TABLE [dbo].[Orders_Monthly_Temp_Table](
[Row] [varchar](200) NOT NULL
) ON [PRIMARY] Crea uno script per 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 Inserisci i dati 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
Creazione di stored procedure e parametri
- Qui i parametri anno e mese sono facoltativi.
- Se un mese non è specificato ci vuole il mese precedente e se il mese è 12 dobbiamo prendere l'anno precedente, perché se stiamo generando il report a gennaio 2019 per dicembre 2018.
- Se un anno non è specificato, prende l'anno corrente e il percorso della cartella è obbligatorio.
CREATE PROCEDURE [dbo].[Orders_Monthly_Report]
@Month INT = NULL
,@Year INT = NULL
,@FolderPath VARCHAR(200)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY Convalida parametri
--#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 Ottieni la configurazione dalla tabella di esportazione
DECLARE @ExportPath VARCHAR(200)
,@Delimiter CHAR(1)
,@FileType VARCHAR(5)
SELECT @ExportPath = TRIM(ShareFolder)
,@FileType = TRIM(FileType)
,@Delimiter = TRIM(Delimiter)
FROM dbo.Export_Config Ottenere la data di inizio e la data di fine del mese
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 Inserisci i dati nella tabella temporanea in un formato specifico, ad es. in questo caso “| – simbolo del tubo separato”
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 Codice per esportare i dati in un file flat
Crea la cartella se non esiste utilizzando 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 Creazione del file nella cartella condivisa
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
Cambia il contesto della directory nella cartella in cui si trova BPC Utility
[id tabella=58 /]
Esecuzione della procedura
DECLARE @return_value int
EXEC @return_value = [dbo].[Exp_Orders_Monthly_Report]
@Month = NULL,
@Year = NULL,
@FolderPath = NULL
SELECT 'Return Value' = @return_value
GO Uscita

Cartella di destinazione

File flat effettivo (.txt/.cvs)

La cartella condivisa dovrebbe avere le autorizzazioni per l'account virtuale "NT SERVICE\MSSQLSERVER"
Fare clic con il pulsante destro del mouse sul file o sulla cartella per cui si desidera impostare le autorizzazioni → Fare clic su Proprietà → Fare clic sulla scheda Sicurezza. → Fare clic su Modifica → Fare clic su Aggiungi → Digitare NT SERVICE\MSSQLSERVER nella casella del nome dell'oggetto. (non fare clic su "Controlla nomi" - se fai clic su Controlla nomi può accadere che venga visualizzato un errore "Impossibile trovare un oggetto denominato "NT SERVICE\MSSQLSERVER".) → Fare clic su OK → scegliere l'account MSSQLSERVER → Aggiungi autorizzazioni ( Controllo completo) necessari per l'account MSSQLSERVER:

Abilita SQL Server 'xp_cmdshell'
EXEC sp_configure 'show advanced options', 1 GO RECONFIGURE GO EXEC sp_configure 'xp_cmdshell', 1 GO RECONFIGURE GO
Come importare dati da file flat
In questo esempio, utilizziamo Bulk Insert per importare i dati dal file. Possiamo anche usare Openrowset ecc.
Crea una stored procedure per importare i dati da un file flat nella cartella condivisa.
In primo luogo, creare gli oggetti dipendenti per la procedura di importazione Stored.
Quindi dobbiamo creare le seguenti tabelle
- Gli Ordini_mensili tabella:questa tabella viene utilizzata per memorizzare i dati degli ordini mensili dal file flat.
- Il Import_Config tabella: questa tabella viene utilizzata per memorizzare le configurazioni di importazione, ad esempio il percorso della cartella condivisa, il tipo di file flat, il delimitatore.

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 Inserisci i dati 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
Creazione di stored procedure e parametri
Come nella procedura di esportazione Stored.
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 Convalida parametri
Come nella procedura di esportazione Stored.
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 Verifica se il file esiste o meno
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 Esecuzione della procedura

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

Verifica


Automatizzazione del processo:
Per eseguire automaticamente il processo di esportazione e importazione in un tempo programmato. supponiamo di dover eseguire l'esportazione il primo giorno del mese alle 00:00 del mese per il report dell'ultimo mese ed eseguire l'importazione in un secondo momento. Quindi dobbiamo creare il lavoro SQL per questo.
Passaggi per creare il lavoro SQL per l'esportazione e l'importazione.
- Apri MS SQL Server Management Studio →
- e dovresti avere "SQL Server Agent" →
- Espandi "SQL Server Agent" in Esplora oggetti. →
- Fai clic con il pulsante destro del mouse su LAVORO e seleziona "Nuovo lavoro..." →
- Puoi vedere la finestra "Nuovo lavoro" e inserire il nome ="Ordini_Esportazione_mensile" &Descrizione

Quindi vai alla scheda Passi → Fai clic sul pulsante Nuovo in basso → si apre una nuova finestra Passaggi del lavoro → Inserisci il nome ="execute [Exp_Orders_Monthly_Report] SP" e Digita ="Transact-SQL Script (T-SQL)" → Incolla il seguente script nell'area di testo Comando e fare clic su 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

Quindi vai alla scheda Pianificazione → Fai clic sul pulsante Nuovo in basso → si apre una nuova finestra Pianificazione lavoro. Inserisci il nome ="Ordina pianificazione mensile" e inserisci i seguenti dettagli e fai clic su OK → Ancora una volta fai clic su OK nella finestra Nuovo lavoro.
Il lavoro verrebbe creato correttamente.


Verifica il processo SQL:
Elimina tutti i file nella cartella condivisa per il test.

Per eseguire il lavoro manualmente per il test:fare clic con il pulsante destro del mouse sul lavoro appena creato → fare clic su "Avvia lavoro al passaggio.." e possiamo vedere il lavoro in esecuzione


Possiamo vedere che il file è stato creato nella cartella condivisa.

Nota:segui i passaggi precedenti per creare anche il lavoro SQL (Orders_Monthly_Import) per l'importazione.
Spero che ora tu abbia una migliore comprensione di come utilizzare l'utilità BCP.
Strumento utile:
dbForge Data Pump:un componente aggiuntivo SSMS per il riempimento di database SQL con dati di origine esterni e la migrazione dei dati tra i sistemi.