web-dev-qa-db-fra.com

BCP pour copier des en-têtes

J'utilise une procédure stockée pour remplir une table avec les données dont j'ai besoin. J'utilise ensuite BCP pour copier les données sur un fichier .csv.

Ce processus fonctionne, la seule chose qu'il manque est que le BCP ne copie pas les noms de champs dans Row1 et je ne vois pas un moyen de définir Header=Yes.

Comment cette syntaxe peut-elle être modifiée pour ajouter la ligne d'en-tête?

declare @sql varchar(8000)
select @sql = 'bcp Test12.dbo.test out C:\testfolder\123.csv -c -t, -T -S '+ @@servername
exec master..xp_cmdshell @sql

Utilisation de Stack Overflow Q & A fourni par Serg, j'ai mis à jour ma syntaxe à:

Select @sql = 'bcp "Select ''abc1'', ''abc2'', ''abc3'', ''abc4'', ''abc5''
UNION ALL Select [abc1], [abc2], [abc3], [abc4],[abc5] from test" queryout "'
Set @sql = @sql + 'C:\testfolder\123.csv' + '" -c -t, -T -S '+@@servername
exec master..xp_cmdshell @sql

Cependant, cela produit une erreur:

Erreur = [Microsoft] [Client native SQL Server 10.0] [SQL Server]
La conversion a échoué lors de la conversion de la date et/ou du temps de la chaîne de caractères.

abc3 Est une colonne DateTime . Devrais-je le convertir différemment? Je n'avais pas besoin de fournir de couler/convertir lorsque j'ai utilisé la syntaxe initiale.

(J'ai également essayé d'utiliser CAST([abc3] As Date) mais qui a jeté la même erreur).

4
user2676140

Le problème avec l'utilisation de UNION Pour inclure les noms de colonne est que les noms de colonne sont des chaînes, mais les champs de la requête de l'Uniond ne sont pas nécessairement des cordes (comme vous l'avez découverte avec cette erreur postée dans la question). Et vous ne pouvez pas convertir des noms en d'autres types tels que INT, DECIMAL, MONEY, DATETIME, etc.

Je n'avais pas besoin de fournir de couler/convertir lorsque j'ai utilisé la syntaxe initiale.

C'est parce que bcp.exe convertissait chaque champ non à chaîne de la table (ou du jeu de résultats) dans une chaîne de sorte qu'elle puisse être placée dans la fichier de sortie. Mais lorsque vous UNION Deux requêtes ou plus ensemble, vous devez vous assurer que chaque position dans chaque SELECT correspond à la même position dans tous les autres SELECTs afin qu'un Le jeu de résultats peut être construit.

Par conséquent, vous êtes laissé avec quelques options:

  1. Utilisez UNION (similaire à ce que vous avez tenté), mais utilisez ensuite CONVERT sur les colonnes de la table qui ne sont pas des chaînes. Par exemple (en supposant que abc1, abc3, et abc4 sont VARCHAR/NVARCHAR _ acb2 est DATETIME, et abc5 est INT):

    UNION ALL SELECT [abc1], CONVERT(NVARCHAR(50), [abc2], 121), [abc3],
    [abc4], CONVERT(NVARCHAR(200), [abc5]) FROM test
    

    L'inconvénient est que vous ne pouvez pas utiliser la syntaxe simple de simplement spécifier le nom de la table.

  2. Créez un fichier texte de la ligne d'en-tête sous forme d'étape séparée, puis exécutez [~ # ~ ~] BCP [~ # ~] , puis concaténate les deux fichiers ensemble. Je montre deux exemples de faire cela dans la réponse DBA.StaCkeXchange suivante: Insérez la ligne d'en-tête personnalisée dans la sortie BCP

  3. Utilisez .NET (SQLCLR ou Console App; ou PowerShell pourrait même fonctionner) pour exécuter la requête et écrire les résultats dans un fichier texte. Lorsque vous utilisez SQLCOMMAND.ExecuteAreaderto run the query, the returnedSome_Code__LDAreader` aura les champs de jeu de résultats (noms, fichiers de données, etc.). Vous pouvez utiliser getschematible pour obtenir les informations de champ de résultat.

    Si cela semble une bonne option, mais que vous ne pouvez pas non plus coder cela ni ne pas avoir le temps et/ou le désir de vous, j'ai créé une procédure stockée SQLCLR qui fait exactement cela, appelé db_bulkexport , et est inclus dans la version complète (ce n'est pas disponible dans la version gratuite) de SQL # . Quelque temps plus tard cette année, il y aura une version d'application console autonome de cette exportation, avec des fonctionnalités supplémentaires :-).

3
Solomon Rutzky