web-dev-qa-db-fra.com

Importation en bloc SQL à partir de CSV

J'ai besoin d'importer un fichier CSV volumineux sur un serveur SQL. J'utilise ceci:

BULK 
INSERT CSVTest
        FROM 'c:\csvfile.txt'
            WITH
    (
                FIELDTERMINATOR = ',',
                ROWTERMINATOR = '\n'
    )
GO

le problème est que tous mes champs sont entourés de guillemets (""), ainsi une ligne ressemble en réalité à:

"1","","2","","sometimes with comma , inside", "" 

Puis-je en gros les importer et dire à SQL d'utiliser les guillemets comme délimiteurs de champs?

Edit : Le problème avec l’utilisation de "", "'comme délimiteur, comme dans les exemples suggérés, est le suivant: Ce que la plupart des exemples font, c’est qu’ils importent les données comprenant le premier" dans la première colonne et le dernier "dans Enfin, ils vont de l'avant et éliminent cela. Hélas, ma première (et dernière) colonne est datetime et ne permettra pas à un "20080902 d'être importé en tant que datetime.

D'après ce que j'ai lu, je pense que FORMATFILE est la voie à suivre, mais la documentation (y compris MSDN) est terriblement inutile.

23
Radu094

Je sais que ce n'est pas une vraie solution, mais j'utilise une table factice pour l'importation avec nvarchar défini pour tout. Ensuite, je fais une insertion qui supprime les "caractères et fait les conversions. Ce n’est pas beau mais ça fait le travail.

3
Alex Andronov

Essayez FIELDTERMINATOR='","'

Voici un excellent lien pour vous aider avec la première et la dernière citation ... regardez comment il a utilisé la sous-chaîne du SP

http://www.sqlteam.com/article/using-bulk-insert-to-load-a-text-file

13
K Richard

Un autre hack que j’utilise parfois est d’ouvrir le fichier CSV dans Excel, puis d’écrire votre requête SQL dans une cellule à la fin de chaque ligne. Par exemple:

=concatenate("insert into myTable (columnA,columnB) values ('",a1,"','",b1,"'")")

Un remplissage peut renseigner ceci dans chaque ligne pour vous. Ensuite, copiez et collez le résultat dans une nouvelle fenêtre de requête.

C'est de la vieille école, mais si vous n'avez besoin que de faire des importations de temps en temps, cela vous évite de perdre votre temps à lire toute la documentation obscure sur la «bonne» façon de le faire.

9
cbp

Essayez OpenRowSet . Cela peut être utilisé pour importer des fichiers Excel. Excel peut ouvrir les fichiers CSV, il vous suffit donc de trouver le bon [ConnectionString] [2].

[2]: Pilote = {Pilote Microsoft Text (* .txt; * .csv)}; Dbq = c:\txtFilesFolder \; Extensions = asc, csv, tab, txt;

4
Daren Thomas

Identifiant, utilisez FileHelpers dans une bibliothèque open source

2
roundcrisis

Vous devez d'abord importer un fichier CSV dans la table de données

Ensuite, vous pouvez insérer des lignes en vrac à l'aide de SQLBulkCopy

using System;
using System.Data;
using System.Data.SqlClient;

namespace SqlBulkInsertExample
{
    class Program
    {
      static void Main(string[] args)
        {
            DataTable prodSalesData = new DataTable("ProductSalesData");

            // Create Column 1: SaleDate
            DataColumn dateColumn = new DataColumn();
            dateColumn.DataType = Type.GetType("System.DateTime");
            dateColumn.ColumnName = "SaleDate";

            // Create Column 2: ProductName
            DataColumn productNameColumn = new DataColumn();
            productNameColumn.ColumnName = "ProductName";

            // Create Column 3: TotalSales
            DataColumn totalSalesColumn = new DataColumn();
            totalSalesColumn.DataType = Type.GetType("System.Int32");
            totalSalesColumn.ColumnName = "TotalSales";

            // Add the columns to the ProductSalesData DataTable
            prodSalesData.Columns.Add(dateColumn);
            prodSalesData.Columns.Add(productNameColumn);
            prodSalesData.Columns.Add(totalSalesColumn);

            // Let's populate the datatable with our stats.
            // You can add as many rows as you want here!

            // Create a new row
            DataRow dailyProductSalesRow = prodSalesData.NewRow();
            dailyProductSalesRow["SaleDate"] = DateTime.Now.Date;
            dailyProductSalesRow["ProductName"] = "Nike";
            dailyProductSalesRow["TotalSales"] = 10;

            // Add the row to the ProductSalesData DataTable
            prodSalesData.Rows.Add(dailyProductSalesRow);

            // Copy the DataTable to SQL Server using SqlBulkCopy
            using (SqlConnection dbConnection = new SqlConnection("Data Source=ProductHost;Initial Catalog=dbProduct;Integrated Security=SSPI;Connection Timeout=60;Min Pool Size=2;Max Pool Size=20;"))
            {
                dbConnection.Open();
                using (SqlBulkCopy s = new SqlBulkCopy(dbConnection))
                {
                    s.DestinationTableName = prodSalesData.TableName;

                    foreach (var column in prodSalesData.Columns)
                        s.ColumnMappings.Add(column.ToString(), column.ToString());

                    s.WriteToServer(prodSalesData);
                }
            }
        }
    }
}
1
kombsh

vous pouvez essayer ce code qui est très doux si vous voulez, cela supprimera les points-virgules indésirables de votre code. si par exemple vos données sont comme ceci:
"Kelly", "Reynold", "[email protected]"

Bulk insert test1
from 'c:\1.txt' with ( 
    fieldterminator ='","'
    ,rowterminator='\n')

update test1<br>
set name =Substring (name , 2,len(name))
where name like **' "% '**

update test1
set email=substring(email, 1,len(email)-1)
where email like **' %" '**
1
PMJ

Vous devez faire attention à BCP/BULK INSERT car ni BSP ni Bulk Insert ne le gèrent bien si la citation n’est pas cohérente, même avec des fichiers de format (même les fichiers de format XML ne proposent pas d’option) et des caractères fictifs ["] à la fin. début et fin et en utilisant [","] comme séparateur. Techniquement, les fichiers CSV n'ont pas besoin de caractères ["] s'il n'y a pas de caractères [] incorporés

C’est pour cette raison que les fichiers délimités par des virgules sont parfois appelés fichiers à comédie limitée.

OpenRowSet nécessitera Excel sur le serveur et pourrait poser problème dans les environnements 64 bits. Je sais que l'utilisation de Excel dans Jet en 64 bits pose problème.

SSIS est vraiment votre meilleur choix si le fichier est susceptible de différer de vos attentes à l’avenir.

1
Cade Roux

Avez-vous besoin de le faire par programme ou est-ce un coup unique?

À l'aide de Enterprise Manager, cliquez avec le bouton droit de la souris sur Importer les données pour sélectionner votre délimiteur.

1
Dana

C'est une vieille question, alors j'écris ceci pour aider tous ceux qui tombent dessus.

SQL Server 2017 introduit le paramètre FIELDQUOTE destiné à ce cas d'utilisation précis.

0
user10191093

Vous pouvez également utiliser DTS ou SSIS.

0
µBio

Avez-vous le contrôle sur le format d'entrée? | (tuyaux), et\t font habituellement de meilleurs terminateurs de champ.

0
jason saldo

Si vous trouvez comment obtenir le fichier analysé dans un DataTable, je suggérerais la classe SqlBulkInsert pour l'insérer dans SQL Server.

0
RKitson

Ouais, K Richard a raison: FIELDTERMINATOR = '","'

Voir http://www.sqlteam.com/article/using-bulk-insert-to-load-a-text-file pour plus d'informations.

0
Epaga