it-swarm.com.de

Wie schreibt man UTF-8-Zeichen mit Masseneinfügung in SQL Server?

Ich mache eine BULK INSERT in sqlserver und fügt UTF-8-Zeichen nicht korrekt in die Datenbank ein. Die Datendatei enthält diese Zeichen, aber die Datenbankzeilen enthalten nach der Masseneinfügungsausführung Speicherzeichen.

Mein erster Verdächtiger war die letzte Zeile der Formatdatei:

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"

Aber nachdem ich diese offizielle Seite gelesen habe, scheint mir dies ein Fehler beim Lesen der Datendatei durch die Einfügeoperation in SQL Server Version 2008 zu sein.

Was ist die Lösung für dieses Problem oder zumindest eine Problemumgehung? 

16
Goran Jovic

Du kannst nicht Sie sollten zuerst ein Datenfeld vom Typ N verwenden, Ihre Datei in UTF-16 konvertieren und dann importieren. Die Datenbank unterstützt kein UTF-8.

27
Michael-O

Ich bin hierher gekommen, bevor ich nach einer Lösung für das Einfügen von Sonderzeichen gesucht habe. Die Umgehung mit UTF-16 (die die doppelte Größe der CSV-Datei verdoppeln würde) hat mir nicht gefallen sehr einfach, du brauchst keine Formatdatei ... Also füge ich diesen Kommentar für andere Leute hinzu, die das Gleiche suchen, da sie anscheinend nirgendwo gut dokumentiert zu sein scheint und ich glaube, dass dies ein Sehr häufiges Problem für Nicht-Englisch sprechende Personen. Die Lösung lautet: Fügen Sie einfach CODEPAGE = '65001' in die with-Anweisung der Masseneinfügung ein. (65001 = Codepage-Nummer für UTF-8) . Funktioniert möglicherweise nicht für alle Unicode-Zeichen, wie von Michael O vorgeschlagen, aber es funktioniert zumindest für Latin-Extended, Griechisch und Kyrillisch, wahrscheinlich viele andere auch.

Hinweis: Die MSDN-Dokumentation besagt, dass Utf-8 nicht unterstützt wird. Glauben Sie mir nicht. Für mich funktioniert das perfekt in SQL Server 2008, andere Versionen wurden jedoch nicht getestet.

z.B.:

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

Wenn alle Ihre Sonderzeichen in 160-255 (iso-8859-1 oder windows-1252) sind, können Sie auch Folgendes verwenden:

BULK INSERT #myTempTable 
FROM  'D:\somefolder\myCSV.txt'+
WITH 
    ( 
        CODEPAGE = 'ACP',
        FIELDTERMINATOR = '|',
        ROWTERMINATOR ='\n'
    );
27
Tom-K
  1. Datei in Excel als CSV speichern (durch Kommas getrennt)
  2. Öffnen Sie die gespeicherte CSV-Datei in Notepad ++
  3. Encoding -> Convert to UCS-2 Big Endian 
  4. Sparen

BULK INSERT #tmpData

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

Erledigt.

7
Janis Rudovskis

Sie können die Datendatei mit UTF-16 neu codieren. Das habe ich trotzdem getan.

4
sayap

Microsoft hat gerade die Unterstützung für UTF-8 zu SQL Server 2014 SP2 hinzugefügt:

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

4
Jon Morisi

Beachten Sie, dass UTF-8 ab Microsoft SQL Server 2016 von bcp , BULK_INSERT (wie in der ursprünglichen Frage enthalten) und OPENROWSET unterstützt wird.

2
Charles Burns

Verwenden Sie diese Optionen - DATAFILETYPE='char' und CODEPAGE = '1252'

2
Heber

Sollten Sie nicht SQLNCHAR anstelle von SQLCHAR für die Unicode-Daten verwenden?

1
AdaTheDev

Ich dachte, ich würde meine Gedanken dazu hinzufügen. Wir haben versucht, Daten mit Hilfe von bcp in SqlServer zu laden und hatten eine Menge Probleme.

bcp unterstützt in den meisten Versionen keine Art von UTF-8-Dateien. Wir haben herausgefunden, dass UTF-16 funktionieren würde, aber es ist komplexer als in diesen Beiträgen gezeigt.

Mit Java haben wir die Datei mit folgendem Code geschrieben: 

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

Dies gab uns die richtigen Daten zum Einfügen.

 utf-16 little-endian

Wir haben versucht, nur UTF16 zu verwenden, und haben immer wieder Fehler EOF erhalten. Dies liegt daran, dass der Stücklistenteil der Datei fehlte. Von Wikipedia:

UTF-16 kann eine Stückliste (U + FEFF) als erstes Zeichen einer Datei oder eines Zeichenstroms platziert werden, um die Endianness (Byte-Reihenfolge) aller 16-Bit-Codeeinheiten der Datei oder des Streams anzuzeigen. 

Wenn diese Bytes nicht vorhanden sind, funktioniert die Datei nicht. Wir haben also die Datei, aber es gibt noch ein Geheimnis, das angegangen werden muss. Bei der Erstellung Ihrer Befehlszeile müssen Sie -w angeben, um bcp mitzuteilen, um welche Art von Daten es sich handelt. Wenn Sie nur englische Daten verwenden, können Sie -c (Zeichen) verwenden. Das sieht dann ungefähr so ​​aus:

bcp dbo.blah in C:\Benutzer\blah\Desktop\events\blah.txt -S tcp: databaseurl, someport -d die Datenbank -U Benutzername -P Kennwort -w

Wenn dies alles erledigt ist, erhalten Sie süße Daten!

 Good little endian!

0
markthegrea

Meine exportierten Daten sind im TSV-Format von DB mit Latin-1-Kodierung.

Dies ist leicht zu überprüfen: SELECT DATABASEPROPERTYEX('DB', 'Collation') SQLCollation;

Die Extraktdatei liegt im UTF-8-Format vor.

BULK INSERT funktioniert nicht mit UTF-8, daher konvertiere ich UTF-8 nach ISO-8859-1 (alias Latin-1) mit einem einfachen Clojure-Skript:

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

Ausführen - korrekte Pfade und Java.exe -cp clojure-1.6.0.jar clojure.main utf8_to_Latin1.clj

0
beloblotskiy

Ich habe die Masseneinfügung mit UTF -8 Format getestet. Es funktioniert gut in 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";

Ich habe *.DAT-Datei mit FS als Spaltentrenner verwendet.

Es ist mir gelungen, dies mit SSIS und einem ADO NET-Ziel anstelle von OLEDB zu tun.

0
JYatesDBA