web-dev-qa-db-ja.com

CSVからのSQL一括インポート

大きなCSVファイルをSQLサーバーにインポートする必要があります。私はこれを使用しています:

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

問題は、すべてのフィールドが引用符( "")で囲まれているため、行は実際には次のようになります。

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

どういうわけかそれらを一括インポートして、引用符をフィールド区切り文字として使用するようにSQLに指示できますか?

編集:提案された例のように、区切り文字として '"、"'を使用する場合の問題は、次のとおりです。ほとんどの例では、最初の列の最初の "と最後の"を含むデータをインポートします。 「最後に、彼らは先に進んでそれを取り除きます。残念ながら、私の最初(および最後)の列は日時であり、「20080902を日時としてインポートすることはできません。

私が周りで読んでいることから、FORMATFILEが進むべき道だと思いますが、ドキュメント(MSDNを含む)はひどく役に立たないです。

23
Radu094

これが実際の解決策ではないことはわかっていますが、インポートにはダミーテーブルを使用し、すべてにnvarcharを設定します。次に、「」文字を取り除き、変換を行う挿入を行います。きれいではありませんが、機能します。

3
Alex Andronov

FIELDTERMINATOR='","'をお試しください

これは最初と最後の引用に役立つ素晴らしいリンクです...彼がSPの部分文字列をどのように使用したかを見てください

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

13
K Richard

私が時々使用するもう1つのハックは、ExcelでCSVを開き、SQLステートメントを各行の最後のセルに書き込むことです。例えば:

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

フィルダウンを使用すると、これをすべての行に入力できます。次に、出力をコピーして新しいクエリウィンドウに貼り付けます。

これは昔ながらの方法ですが、たまにインポートを実行するだけでよい場合は、「適切な」方法ですべてのあいまいなドキュメントを読む手間を省くことができます。

9
cbp

OpenRowSet を試してください。これは、Excelのものをインポートするために使用できます。 ExcelはCSVファイルを開くことができるため、正しい[ConnectionString] [2]を理解するだけで済みます。

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

4
Daren Thomas

FileHelpersをオープンソースライブラリとして使用すると思います

2
roundcrisis

CSVファイルをデータテーブルにインポートする必要がある

次に、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

必要に応じてこのコードを試すことができます。これにより、コードから不要なセミコロンが削除されます。たとえば、データが次のような場合:
"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

フォーマットファイル(XMLフォーマットファイルでもオプションが提供されていない)やダミーの["]文字を使用しても、引用符が一貫していない場合、BSPもバルクインサートもこれを適切に処理しないため、BCP/BULKINSERTに注意する必要があります。開始と終了、および区切り文字として["、"]を使用します。技術的には、CSVファイルには[、]文字が埋め込まれていない場合、["]文字を含める必要はありません。

カンマ区切りのファイルがコメディ限定ファイルと呼ばれることがあるのはこのためです。

OpenRowSetはサーバー上にExcelを必要とし、64ビット環境では問題が発生する可能性があります。64ビットのJetでExcelを使用すると問題が発生する可能性があります。

ファイルが将来予想と異なる可能性がある場合は、SSISが最善の策です。

1
Cade Roux

これをプログラムで行う必要がありますか、それとも1回限りのショットですか?

Enterprise Managerを使用して、「データのインポート」を右クリックすると、区切り文字を選択できます。

1
Dana

これは古い質問なので、つまずいた人を助けるためにこれを書いています。

SQL Server 2017では、この正確なユースケースを対象としたFIELDQUOTEパラメーターが導入されています。

0
user10191093

DTSまたはSSISを使用することもできます。

0
µBio

入力フォーマットを制御できますか? | (パイプ)、および\ tは通常、より優れたフィールドターミネータになります。

0
jason saldo

ファイルを解析してDataTableに入れる方法がわかった場合は、SQLServerに挿入するためのSqlBulkInsertクラスをお勧めします。

0
RKitson

うん、Kリチャードは正しい:FIELDTERMINATOR = '","'

詳細については、 http://www.sqlteam.com/article/using-bulk-insert-to-load-a-text-file を参照してください。

0
Epaga