web-dev-qa-db-fra.com

Insérer en bloc un fichier CSV correctement cité dans SQL Server

J'essaie d'importer un fichier CSV correctement cité, ce qui signifie que les données ne sont citées que si elles contiennent une virgule, par exemple:

41, Terminator, Black
42, "Monsters, Inc.", Blue

Je remarque que la première ligne est importée correctement, mais que la deuxième ligne présente une erreur suggérant que la virgule citée a été traitée comme un séparateur de champ.

J'ai vu des suggestions comme celle-ci

Importation SQL en bloc de CSV

changer le terminateur de champ

FIELDTERMINATOR = '","'

Cependant, mon fichier CSV ne cite que les champs qui en ont besoin. Je ne pense donc pas que cette suggestion fonctionnerait.

L'instruction BULK IMPORT de SQL Server peut-elle importer un fichier CSV correctement cité? Comment?

44
Eric J.

Malheureusement, SQL Server interprète la virgule citée comme un délimiteur. Ceci s’applique à la fois au BCP et à l’insert en vrac.

De http://msdn.Microsoft.com/en-us/library/ms191485%28v=sql.100%29.aspx

Si un caractère de terminaison apparaît dans les données, il est interprété comme un terminateur, pas en tant que données, et les données après ce caractère sont interprété comme appartenant au champ ou à l'enregistrement suivant. Donc, choisissez vos terminateurs avec soin pour vous assurer qu'ils n'apparaissent jamais dans vos données.

27
iruvar

Il existe une autre solution pour cela.

Considérez les guillemets comme faisant partie du délimiteur de champs, en modifiant le fichier fmt.

Vous pouvez vérifier ceci pour plus d'informations:

http://blogs.msdn.com/b/sqlserverfaq/archive/2010/02/04/how-to-remove-unwanted-quotation-marks-while-importing-a-data-file.aspx

Un extrait du lien ci-dessus:

La seule façon de supprimer les guillemets serait de modifier les délimiteurs de colonne spécifiés lors de l'opération d'importation. Le seul inconvénient ici est que si vous inspectez les données à insérer, vous vous rendrez vite compte que les délimiteurs de colonne sont différents pour chaque colonne (délimiteurs mis en évidence ci-dessus).

Ainsi, pour spécifier des délimiteurs de colonne différents pour chaque colonne, vous devez utiliser un fichier de format si vous envisagez d’utiliser Bulk Insert ou BCP. Si vous générez un fichier de format pour la structure de tableau ci-dessus, ce serait comme suit:

9.0
3
1       SQLCHAR       0       5       "\t"     1     FName              SQL_Latin1_General_CP1_CI_AS
2       SQLCHAR       0       5       "\t"     2     LName              SQL_Latin1_General_CP1_CI_AS
3       SQLCHAR       0       50      "\r\n"   3     Company            SQL_Latin1_General_CP1_CI_AS

Modifiez le fichier de format pour représenter les délimiteurs de colonne corrects pour chaque colonne. Le nouveau fichier de format à utiliser ressemblera à ceci:

9.0
4
1       SQLCHAR       0       0     "\""      0     FIRST_QUOTE      SQL_Latin1_General_CP1_CI_AS
2       SQLCHAR       0       5     "\",\""   1     FNAME               SQL_Latin1_General_CP1_CI_AS
3       SQLCHAR       0       5     "\",\""   2     LNAME            SQL_Latin1_General_CP1_CI_AS
4       SQLCHAR       0       50    "\"\r\n"  3     COMPANY          SQL_Latin1_General_CP1_CI_AS
17
Rafael Segovia

Je sais qu'il s'agit d'un sujet ancien, mais cette fonctionnalité est désormais implémentée depuis SQL Server 2017. Le paramètre que vous recherchez est FIELDQUOTE = dont la valeur par défaut est '"'. Pour plus d'informations, consultez https://docs.Microsoft.com/fr-fr/sql/t-sql/statement/bulk-insert-transact-sql? view = sql-server-2017

8
Dominix

Assurez-vous d’avoir activé l’option TextQualified et d’avoir la valeur ".

8
Bangxin

J'ai eu le même problème et je ne voulais pas suivre la route SSIS. J'ai donc trouvé un script PowerShell facile à exécuter qui gère la casse des guillemets avec la virgule dans ce champ particulier:

Code source et DLL pour le script PowerShell: https://github.com/billgraziano/CsvDataReader

Voici un blog qui explique l'utilisation: http://www.sqlteam.com/article/fast-csv-import-in-powershell-to-sql-server

3
Todd

Vous pouvez également envisager d’utiliser OpenRowSet avec le fournisseur de données de fichier texte CSV.

Cela devrait être possible avec n’importe quelle version de SQL Server> = 2005 bien que vous deviez activer la fonctionnalité.

http://social.msdn.Microsoft.com/forums/en-US/sqldataaccess/thread/5869d247-f0a0-4224-80b3-ff2e414be402

3
Paul-Andre Panon

J'ai passé une demi-journée sur ce problème. Il est préférable d'importer à l'aide de l'assistant de données d'importation et d'exportation de SQL Server. Il existe un paramètre dans cet assistant qui résout ce problème. Images détaillées ici: https://www.mssqltips.com/sqlservertip/1316/strip-double-quotes-from-an-import-file-in-integration-services-ssis/ Merci

2
mye.morr

J'ai eu le même problème, avec des données qui ne font qu'occasionnellement des guillemets doubles du texte… .. Ma solution est de laisser BULK LOAD importer les guillemets, puis d'exécuter un REPLACE sur les données importées.

Par exemple:

en vrac insérer CodePoint_tbl à partir de "F:\Data\Map\CodePointOpen\Data\CSV\ab.csv" avec (FIRSTROW = 1, FIELDTERMINATOR = ',', ROWTERMINATOR = '\ n');

mettre à jour CodePoint_tbl set Postcode = replace (Postcode, '"', '') where charindex ('"', Postcode)> 0

Pour rendre le script REPLACE moins pénible, copiez et collez ce dont vous avez besoin à partir des résultats suivants:

select C.ColID, C.[name] as Columnname into #Columns
from syscolumns C
join sysobjects T on C.id = T.id
where T.[name] = 'User_tbl'
order by 1;

declare @QUOTE char(1);
set @QUOTE = Char(39);
select 'Update User_tbl set '+ColumnName+'=replace('+ColumnName+','
 + @QUOTE + '"' + @QUOTE + ',' + @QUOTE + @QUOTE + ');
GO'
from #Columns
where ColID > 2
order by ColID;
1
Keith MacDonald

Selon les spécifications de format CSV, je ne pense pas que le fait que les données soient correctement ou non citées importe peu, tant que les spécifications sont respectées. Les citations excessives doivent être traitées par l'analyseur, s'il est correctement implémenté. FIELDTERMINATOR doit être une virgule et ROWTERMINATOR est fin de ligne - il s'agit d'un fichier CSV standard. Avez-vous essayé d'importer vos données avec ces paramètres?

0
Neolisk