web-dev-qa-db-ja.com

SQL Serverで一括挿入を使用してUTF-8文字を記述する方法

SqlserverにBULK INSERTを実行していますが、データベースにUTF-8文字を適切に挿入していません。データファイルにはこれらの文字が含まれていますが、一括挿入の実行後、データベース行には文字化けが含まれています。

私の最初の容疑者はフォーマットファイルの最後の行でした:

10.0
3
1 SQLCHAR  0  0  "{|}"  1 INSTANCEID ""
2 SQLCHAR  0  0  "{|}"  2 PROPERTYID ""
3 SQLCHAR  0  0  "[|]"  3 CONTENTTEXT "SQL_Latin1_General_CP1_CI_AS"

しかし、 この公式ページ を読んだ後、これは実際にはSQL Serverバージョン2008での挿入操作によるデータファイルの読み取りのバグのようです。バージョン2008 R2を使用しています。

この問題の解決策または少なくとも回避策は何ですか?

20
Goran Jovic

できません。最初にNタイプのデータフィールドを使用し、ファイルをUTF-16に変換してからインポートする必要があります。データベースはUTF-8をサポートしていません。

28
Michael-O

特殊文字を一括挿入するソリューションを探す前にここに来ました。 UTF-16での回避策(csvファイルのサイズが2倍になる)が好きではありませんでした。間違いなくCANを使用でき、フォーマットファイルは必要ないことが非常に簡単であることがわかりました。この答えは同じものを探している他の人々のためです。なぜならそれはどこにもうまく文書化されていないようで、私はこれが非英語圏の人々にとって非常に一般的な問題だと思います。解決策は、一括挿入のwithステートメント内にCODEPAGE = '65001'を追加するだけです。 (65001 = UTF-8のコードページ番号)。 Michael Oが示唆するように、すべてのユニコード文字で機能するわけではありませんが、少なくともラテン語拡張、ギリシャ語、キリル文字、おそらく他の多くの言語でも完璧に機能します。

注:MSDNのドキュメントでは、utf-8はサポートされていませんが、信じられません。これはSQL Server 2008で完璧に機能しますが、他のバージョンは試用しませんでした。

例えば。:

BULK INSERT #myTempTable 
FROM  'D:\somefolder\myCSV.txt'+
WITH 
    ( 
        CODEPAGE = '65001',
        FIELDTERMINATOR = '|',
        ROWTERMINATOR ='\n'
    );

すべての特殊文字が160-255(iso-8859-1またはwindows-1252)にある場合は、次も使用できます。

BULK INSERT #myTempTable 
FROM  'D:\somefolder\myCSV.txt'+
WITH 
    ( 
        CODEPAGE = 'ACP',
        FIELDTERMINATOR = '|',
        ROWTERMINATOR ='\n'
    );
35
Tom-K
  1. ExcelでCSV(カンマ区切り)としてファイルを保存します
  2. 保存したCSVファイルをnotepad ++で開く
  3. エンコーディング-> UCS-2ビッグエンディアンへの変換
  4. セーブ

一括挿入#tmpData

    FROM 'C:\Book2.csv'
    WITH
    (
        FIRSTROW = 2,
        FIELDTERMINATOR = ';',  --CSV field delimiter
        ROWTERMINATOR = '\n',   --Use to shift the control to next row
        TABLOCK
    )

できた.

8
Janis Rudovskis

Microsoftは、SQL Server 2014 SP2にUTF-8サポートを追加しました。

https://support.Microsoft.com/en-us/kb/313678

5
Jon Morisi

UTF-16でデータファイルを再エンコードできます。とにかくそうしました。

4
sayap

Microsoft SQL Server 2016以降、UTF-8は bcpBULK_INSERT(元の質問の一部として) 、および OPENROWSET

2
Charles Burns

これらのオプションを使用します-DATAFILETYPE='char'およびCODEPAGE = '1252'

2
Heber

UnicodeデータにSQLNCHARの代わりにSQLCHARを使用するべきではありませんか?

1
AdaTheDev

私はこれに私の考えを追加すると思いました。 bcpを使用してSqlServerにデータをロードしようとしており、多くの問題がありました。

ほとんどのバージョンでは、bcpはどのタイプのUTF-8ファイルもサポートしていません。 UTF-16が機能することを発見しましたが、これらの投稿に示されているよりも複雑です。

Javaを使用して、次のコードを使用してファイルを作成しました。

PrintStream fileStream = new PrintStream(NEW_TABLE_DATA_FOLDER + fileName, "x-UTF-16LE-BOM");

これにより、挿入する正しいデータが得られました。

utf-16 little-endian

UTF16のみを使用して、EOFエラーを取得し続けました。これは、ファイルのBOM部分が欠落しているためです。ウィキペディアから:

UTF-16、BOM(U + FEFF)をファイルまたは文字ストリームの最初の文字として配置して、ファイルまたはストリームのすべての16ビットコード単位のエンディアン(バイト順)を示すことができます。

これらのバイトが存在しない場合、ファイルは機能しません。ファイルはありますが、対処する必要があるもう1つの秘密があります。コマンドラインを作成するときは、-wを含めて、bcpにどのタイプのデータかを伝える必要があります。英語のデータのみを使用する場合は、-c(文字)を使用できます。そのため、次のようになります。

c:\ Users\blah\Desktop\events\blah.txtのbcp dbo.blah -S tcp:databaseurl、someport -d thedatabase -Uユーザー名-Pパスワード-w

これがすべて完了すると、見栄えの良いデータが得られます!

Good little endian!

0
markthegrea

私のエクスポートされたデータは、Latin-1エンコーディングを持つDBからのTSV形式です。

これは簡単に確認できます:SELECT DATABASEPROPERTYEX('DB', 'Collation') SQLCollation;

抽出ファイルはUTF-8形式です。

BULK INSERTはUTF-8では機能しないため、単純なClojureスクリプトを使用してUTF-8をISO-8859-1(別名Latin-1)に変換します。

(spit ".\\dump\\file1.txt" (Slurp ".\\dump\\file1_utf8.txt" :encoding "UTF-8") :encoding "ISO-8859-1")

実行するには-正しいパスとJava.exe -cp clojure-1.6.0.jar clojure.main utf8_to_Latin1.clj

0
beloblotskiy

UTF -8形式で一括挿入をテストしました。 SQL Server 2012では正常に動作します。

string bulkInsertQuery = @"DECLARE @BulkInsertQuery NVARCHAR(max) = 'bulk insert [dbo].[temp_Lz_Post_Obj_Lvl_0]
                                      FROM ''C:\\Users\\suryan\\Desktop\\SIFT JOB\\New folder\\POSTdata_OBJ5.dat''
                                      WITH ( FIELDTERMINATOR =  '''+ CHAR(28) + ''', ROWTERMINATOR = ''' +CHAR(10) + ''')'
                                      EXEC SP_EXECUTESQL @BulkInsertQuery";

列の区切りとしてFSを使用した*.DATファイルを使用していました。

私はSSISとOLEDBの代わりにADO NET宛先を使用してこれを行うことができました。

0
JYatesDBA