Как писать символы UTF-8 с помощью массовой вставки в SQL Server?

Я делаю BULK INSERT в sqlserver и не вставляю символы 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.

Каково решение этой проблемы или, по крайней мере, обходной путь?

Ответы

Ответ 1

Вы не можете. Сначала вы должны использовать поле данных типа N, преобразовать свой файл в UTF-16 и затем импортировать его. База данных не поддерживает UTF-8.

Ответ 2

Я пришел сюда, прежде чем искать решение для массовой вставки специальных символов. Не понравился обходной путь с UTF-16 (это удвоило бы размер CSV файла). Я обнаружил, что вы определенно МОЖЕТЕ, и это очень просто, вам не нужен формат файла. Этот ответ предназначен для других людей, которые ищут то же самое, так как, кажется, это нигде не задокументировано, и я считаю, что это очень распространенная проблема для не говорящих по-английски людей. Решение: просто добавьте CODEPAGE = '65001' внутри оператора with массовой вставки. (65001 = номер кодовой страницы для UTF-8). Может работать не для всех символов Юникода, как это было предложено Майклом О, но, по крайней мере, он отлично работает для латинского, греческого и кириллического алфавита, возможно, для многих других.

Примечание: документация 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'
    );

Ответ 3

  • В excel сохранить файл как CSV (с разделителями-запятыми)
  • Открыть сохраненный CSV файл в блокноте ++
  • Кодирование → Преобразование tO UCS-2 Big Endian
  • Сохранить

BULK INSERT #tmpData​​p >

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

Готово.

Ответ 4

Вы можете перекодировать файл данных с помощью UTF-16. Это все, что я сделал.

Ответ 6

Используйте эти параметры - DATAFILETYPE='char' и CODEPAGE = '1252'

Ответ 8

Разве вы не используете SQLNCHAR вместо SQLCHAR для данных Unicode?

Ответ 9

Мне удалось сделать это с помощью SSIS и назначения ADO NET вместо OLEDB.

Ответ 10

Мои экспортированные данные находятся в формате TSV из базы данных с кодировкой Latin-1.

Это легко проверить: SELECT DATABASEPROPERTYEX('DB', 'Collation') SQLCollation;

Экстрактивный файл находится в формате UTF-8.

BULK INSERT не работает с UTF-8, поэтому я конвертирую UTF-8 в ISO-8859-1 (aka Latin-1) с простым Clojure script:

(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

Ответ 11

Я проверил объемную вставку с UTF -8 Format. Он отлично работает на 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";

Я использовал файл *.DAT с FS в качестве разделителя столбцов.

Ответ 12

Преобразование файла utf-8 в utf-16 используя iconv:

iconv -f utf-8 -t utf-16le < in.txt > out.txt

Ответ 13

Думаю, я бы добавил к этому свои мысли. Мы пытались загрузить данные в SqlServer с помощью bcp и имели массу проблем.

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. Это связано с тем, что нам не хватает части спецификации этого файла. Материал из Википедии:

UTF-16, спецификация (U + FEFF) может быть помещена в качестве первого символа файла или символьного потока для указания конечности (порядка байтов) всех 16-разрядных блоков кода файла или потока.

Если эти байты отсутствуют, файл не будет работать. Итак, у нас есть файл, но есть еще один секрет, который нужно решить. При построении командной строки вы должны указать -w, чтобы сообщить bcp, какой тип данных он имеет. При использовании только английских данных вы можете использовать -c (символ). Итак, это будет выглядеть примерно так:

bcp dbo.blah в C:\Users\blah\Desktop\events\blah.txt -S tcp: databaseurl, someport -d thedatabase -U username -P password -w

Когда все это будет сделано, вы получите несколько приятных данных!

Хороший маленький конец!