Как написать символы UTF-8, используя массовую вставку в SQL Server? - PullRequest
18 голосов
/ 31 марта 2011

Я делаю 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.

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

Ответы [ 12 ]

31 голосов
/ 23 мая 2013

Я пришел сюда, прежде чем искать решение для массовой вставки специальных символов. Не понравился обходной путь с 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'
    );
27 голосов
/ 27 июля 2011

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

8 голосов
/ 07 января 2015
  1. В Excel сохранить файл в формате CSV (через запятую)
  2. Открыть сохраненный файл CSV в блокноте ++
  3. Кодировка -> Преобразовать в UCS-2 Big Endian
  4. Сохранить

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
    )

Готово.

4 голосов
/ 12 июля 2016

Microsoft только что добавила поддержку UTF-8 в SQL Server 2014 SP2:

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

4 голосов
/ 19 апреля 2011

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

2 голосов
/ 20 июля 2016

Обратите внимание, что в Microsoft SQL Server 2016 UTF-8 поддерживается bcp, BULK_INSERT (как было частью исходного вопроса) и OPENROWSET.

2 голосов
/ 26 июня 2015

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

1 голос
/ 31 марта 2011

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

0 голосов
/ 15 марта 2017

Думаю, я бы добавил свои мысли к этому. Мы пытались загрузить данные в 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 пароль -w

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

Good little endian!

0 голосов
/ 12 августа 2015

Я протестировал массовую вставку в формате 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";

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...