L'utilitaire BCP (Bulk Copy Program) de SQL Server permet aux administrateurs de bases de données d'importer des données dans une table et d'exporter des données d'une table vers un fichier plat. L'utilitaire BCP prend également en charge diverses fonctionnalités qui facilitent le processus d'exportation et d'importation des données en masse.
Commençons maintenant avec un scénario d'entreprise.
Scénario d'entreprise
Disons que nous devons partager un rapport mensuel dans le format spécifique à un client dans un emplacement partagé sécurisé comme SFTS, c'est-à-dire qu'au début de chaque mois, nous devons envoyer le fichier à un client pour le mois précédent. Dans ce scénario, nous allons essayer de créer la procédure stockée pour générer des données et exporter ces données vers le fichier plat (.txt ou .csv).
Comment importer et exporter les données SQL ?
Il existe plusieurs façons de procéder :
- À l'aide de SSMS, exécutez la requête dans la fenêtre de requête et l'assistant d'exportation ou d'importation et d'exportation SQL Server.
- Utilisation de SSIS :création d'un package à l'aide de SSDT.
- Utilisation de SSRS.
- Utilisation de C# – Créer une console ou gagner une application à exporter.
- Utilitaire BCP.
- etc.
Qu'est-ce que l'utilitaire BCP ?
L'utilitaire BCP (Bulk copy program) est un utilitaire de ligne de commande permettant de copier des données entre une instance de MS SQL Server et un fichier de données dans un format spécifié par l'utilisateur. Nous pouvons exporter et importer de grandes quantités de données dans et hors des bases de données SQL Server rapidement et facilement.
L'utilitaire BCP effectue les tâches suivantes :
- Exportation de données en masse d'une table SQL Server vers un fichier de données
- Exportation de données en bloc à partir d'une requête/procédure stockée.
- Importation de données en bloc depuis un fichier de données vers une table SQL Server
- Génération des fichiers de format.
Vous pouvez trouver plus de détails sur BCP Utility ici.
Environnement utilisé
- SQL Server 2017 Édition Développeur
- Studio de gestion SQL Server 2017
- Exemple de base de données des importateurs mondiaux v1.0
- Utilitaire BCP
Comment exporter des données vers un fichier plat
Créez une procédure stockée pour générer les données du rapport mensuel.
Tout d'abord, créez les objets dépendants pour la procédure stockée d'exportation.
Nous devons donc créer les tables suivantes :
- La Orders_Monthly_Temp_Table table :cette table temporaire est utilisée pour stocker les données des commandes mensuelles dans un format spécifique pour les exporter vers un fichier texte, c'est-à-dire dans notre cas, concaténer toutes les colonnes en une seule ligne avec le délimiteur "|".
- La Export_Config table :cette table est utilisée pour stocker les configurations d'exportation, c'est-à-dire le chemin du dossier partagé, le type de fichier plat, le délimiteur.
Créer un script pour Orders_Monthly_Temp_Table
CREATE TABLE [dbo].[Orders_Monthly_Temp_Table]( [Row] [varchar](200) NOT NULL ) ON [PRIMARY]
Créer un script pour 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
Insérer des données dans 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
Création &Paramètres de procédure stockée
- Ici, les paramètres d'année et de mois sont facultatifs.
- Si un mois n'est pas spécifié, il prend le mois précédent et si le mois est 12, nous devons prendre l'année précédente, car si nous générons le rapport en janvier 2019 pour décembre 2018.
- Si une année n'est pas spécifiée, il prend l'année en cours et le chemin du dossier est obligatoire.
CREATE PROCEDURE [dbo].[Orders_Monthly_Report] @Month INT = NULL ,@Year INT = NULL ,@FolderPath VARCHAR(200) AS BEGIN SET NOCOUNT ON; BEGIN TRY
Validation des paramètres
--#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
Obtenir la configuration à partir du tableau d'exportation
DECLARE @ExportPath VARCHAR(200) ,@Delimiter CHAR(1) ,@FileType VARCHAR(5) SELECT @ExportPath = TRIM(ShareFolder) ,@FileType = TRIM(FileType) ,@Delimiter = TRIM(Delimiter) FROM dbo.Export_Config
Obtenir la date de début et la date de fin du mois
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
Insérez les données dans la table temporaire dans un format spécifique, c'est-à-dire dans ce cas "| – symbole de tuyau séparé"
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 pour exporter les données vers un fichier plat
Créer le dossier s'il n'existe pas en utilisant 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
Création du fichier dans le dossier partagé
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
Modifiez le contexte de votre répertoire dans le dossier où se trouve l'utilitaire BPC
[identifiant de table=58 /]
Exécuter la procédure
DECLARE @return_value int EXEC @return_value = [dbo].[Exp_Orders_Monthly_Report] @Month = NULL, @Year = NULL, @FolderPath = NULL SELECT 'Return Value' = @return_value GO
Sortie
Dossier de destination
Fichier plat réel (.txt/.cvs)
Le dossier partagé doit avoir des autorisations sur le compte virtuel "NT SERVICE\MSSQLSERVER"
Cliquez avec le bouton droit sur le fichier ou le dossier dont vous souhaitez définir les autorisations → Cliquez sur Propriétés → Cliquez sur l'onglet Sécurité. → Cliquez sur Modifier → Cliquez sur Ajouter → Tapez NT SERVICE\MSSQLSERVER dans la zone de nom d'objet. (ne cliquez pas sur "Vérifier les noms" - si vous cliquez sur Vérifier les noms, il peut arriver que vous obteniez une erreur "Un objet nommé "NT SERVICE\MSSQLSERVER" est introuvable.) → Cliquez sur OK → choisissez le compte MSSQLSERVER → Ajouter des autorisations ( Contrôle total) nécessaires au compte MSSQLSERVER :
Activer le serveur SQL "xp_cmdshell"
EXEC sp_configure 'show advanced options', 1 GO RECONFIGURE GO EXEC sp_configure 'xp_cmdshell', 1 GO RECONFIGURE GO
Comment importer des données à partir d'un fichier plat
Dans cet exemple, nous utilisons Bulk Insert pour importer des données à partir du fichier. Nous pouvons également utiliser Openrowset etc.
Créez une procédure stockée pour importer les données d'un fichier plat dans le dossier partagé.
Tout d'abord, créez les objets dépendants pour la procédure stockée d'importation.
Nous devons donc créer les tables suivantes
- Les commandes_mensuelles table :cette table est utilisée pour stocker les données de commandes mensuelles du fichier plat.
- La Import_Config tableau : cette table est utilisée pour stocker les configurations d'importation, c'est-à-dire le chemin du dossier partagé, le type de fichier plat, le délimiteur.
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
Insérer des données dans 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
Création &Paramètres de procédure stockée
Identique à la procédure stockée d'exportation.
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
Validation des paramètres
Identique à la procédure stockée d'exportation.
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
Vérifiez si le fichier existe ou non
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
Exécution de la procédure
DECLARE @return_value int EXEC @return_value = [dbo].[Imp_Orders_Monthly_Report] @Month = NULL, @Year = NULL, @FolderPath = NULL SELECT 'Return Value' = @return_value GO
Sortie
Vérification
Automatisation du processus :
Pour exécuter automatiquement le processus d'exportation et d'importation à une heure planifiée. disons que nous devons exécuter l'exportation le premier jour du mois à 12h00 du mois pour le dernier rapport du mois et exécuter l'importation plus tard. Nous devons donc créer le travail SQL pour cela.
Étapes pour créer la tâche SQL pour l'exportation et l'importation.
- Ouvrir MS SQL Server Management Studio →
- et vous devriez avoir le "SQL Server Agent" →
- Développez "SQL Server Agent" dans l'Explorateur d'objets. →
- Cliquez avec le bouton droit de la souris sur JOB et sélectionnez « Nouvelle tâche… » →
- Vous pouvez voir la fenêtre "Nouvelle tâche" et saisir le nom ="Orders_Monthly_Export" &Description
Ensuite, allez dans l'onglet Étapes → Cliquez sur le bouton Nouveau en bas → une nouvelle fenêtre Étapes du travail s'ouvre → Entrez le nom ="execute [Exp_Orders_Monthly_Report] SP" et tapez ="Transact-SQL Script (T-SQL)" → Collez le script suivant dans la zone de texte Commande et cliquez sur 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
Ensuite, allez dans l'onglet Planification → Cliquez sur le bouton Nouveau en bas → une nouvelle fenêtre de planification du travail s'ouvre. Entrez le nom ="Programme mensuel de commande" et entrez les détails suivants et cliquez sur OK → Cliquez à nouveau sur OK dans la fenêtre Nouvelle tâche.
Le travail serait créé avec succès.
Testez la tâche SQL :
Supprimez tous les fichiers du dossier partagé pour les tests.
Pour exécuter le travail manuellement à des fins de test :cliquez avec le bouton droit sur le travail nouvellement créé → cliquez sur "Démarrer le travail à l'étape .." et nous pouvons voir le travail en cours d'exécution
Nous pouvons voir que le fichier est créé dans le dossier partagé.
Remarque :Veuillez suivre les étapes ci-dessus pour créer également la tâche SQL (Orders_Monthly_Import) pour l'importation.
J'espère que vous comprenez maintenant mieux comment utiliser l'utilitaire BCP.
Outil utile :
dbForge Data Pump - un complément SSMS pour remplir les bases de données SQL avec des données sources externes et migrer les données entre les systèmes.