Как использовать сортировку UTF-8 в базе данных SQL Server?

84

Я перенес базу данных с mysql на SQL Server (политика), исходную базу данных mysql с использованием UTF8.

Теперь я прочитал /dba/7346/sql-server-2005-2008-utf-8-collation-charset, что SQL Server 2008 не поддерживает utf8, это шутка?

На SQL Server размещено несколько баз данных, в основном с латинской кодировкой. Поскольку перенесенная база данных предназначена для веб-публикации, я хочу сохранить кодировку utf8. Я что-то пропустил или мне нужно добавить / дек на уровне приложения?

Teson
источник
На самом деле нет проблем с использованием UTF8, создав SQLCLR UDF, и вы можете загрузить код от Microsoft. проверьте эту ссылку: technet.microsoft.com/en-us/library/ms160893(v=sql.90).aspx
Ронен
1
Стоит отметить, что Java, JavaScript, DotNet и Windows внутренне используют UTF-16, поэтому, если ваш веб-сайт должен быть закодирован в любом из них, вы сохраняете преобразование в UTF16.
Бен
1
Если это поможет, вы можете представить, что SQL Server внутренне хранит текст как UTF-8; и драйвер преобразует его обратно в UTF-16, когда вы его извлекаете. Вы также можете представить, что SQL Server хранит текст как UCS-32. Формат внутренней памяти не имеет отношения к реализации. Важно то, что базы данных возвращают символьные данные Unicode в формате UTF-16 (что соответствует вашей среде программирования).
Ian Boyd

Ответы:

26

Нет! Это не шутка.

Взгляните здесь: http://msdn.microsoft.com/en-us/library/ms186939.aspx

Типы символьных данных, которые являются данными фиксированной длины, nchar или переменной длины, nvarchar, Unicode и используют набор символов UNICODE UCS-2.

А также здесь: http://en.wikipedia.org/wiki/UTF-16

Более старый UCS-2 (2-байтовый универсальный набор символов) представляет собой аналогичную кодировку символов, которая была заменена UTF-16 в версии 2.0 стандарта Unicode в июле 1996 года.

Edze
источник
Хорошо. Может ли mssql-client выполнять перевод во внешний мир UTF8?
Teson
mssql-clientможет быть все. Java, .NET, C, PHP и т.д ... что значит клиент?
edze
1
Клиент: расширение sqlsrv под php. Роберт помещает это в открытый текст здесь: social.msdn.microsoft.com/Forums/en/sqldriverforphp/thread/… , оценит и опубликует результаты.
Teson
2
Еще раз привет, извините за задержку, но спасибо за представителей, используя sqlsrv_connect (, array ("CharacterSet" => "UTF-8") .. в строке подключения работает нормально. PDO отсутствует, верно?
Teson
33

UTF-8 - это не набор символов, это кодировка. Набор символов для UTF-8 - Unicode. Если вы хотите сохранить текст Unicode, вы используете nvarcharтип данных.

Если база данных будет использовать UTF-8 для хранения текста, вы все равно не получите текст как закодированные данные UTF-8, вы получите его как декодированный текст.

Вы можете легко сохранить текст в кодировке UTF-8 в базе данных, но тогда вы не сохраните его как текст, вы сохраните его как двоичные данные ( varbinary).

Гуффа
источник
Спасибо за вклад. Об этом можно подробнее узнать, например, на stackoverflow.com/questions/3951722/…
Teson
Я не могу понять это. «Набор символов для UTF8 - Unicode» ?? Разве utf8 не шире, чем Unicode. Сохранение Dauðalogn в Юникоде против utf8 дает различные результаты: (EF BB BF) 44 61 75 61 С3 В0 6C 6F 67 6М против \ u0044 \ u0061 \ u0075 \ u00f0 \ u0061 \ u006c \ u006f \ u0067 \ u006e
Teson
2
@ user247245: UTF-8 - это кодировка, а Unicode - набор символов. UTF-8 - один из способов сохранения Unicode. То, что вы использовали для представления Unicode, - это escape-коды, используемые в строковых литералах, что обычно не так, как вы представляете Unicode в виде файла. UTF-32 будет наиболее близким переводом непосредственно из Uncode в формат файла, где каждый код символа сохраняется как 32-битное число.
Guffa
Не могли бы вы объяснить, почему третья буква в приведенном выше примере представлена ​​в UTF8 как C3 B0, а в юникоде как просто F0. Спасибо за вашу помощь.
Teson
4
@ user247245: коды символов между 8 и 11 битами кодируются как 110xxxxx 10xxxxxxв UTF-8 (где xпредставляют биты данных), поэтому код символа F0( 00011110000как 11 битов) кодируется как 11000011 10110000(вставка 00011из кода символа в первый байт и 110000во второй ) что есть C3 B0.
Guffa
24

Похоже, это наконец-то будет поддерживаться в SQL Server 2019! SQL Server 2019 - что нового?

Из BOL:

Поддержка UTF-8

Полная поддержка широко используемой кодировки символов UTF-8 в качестве кодировки импорта или экспорта, а также сортировки на уровне базы данных или столбца для текстовых данных. UTF-8 допускается в CHARи VARCHARтипов данных, и включается при создании или изменении сверку объекта в сопоставлении сUTF8 суффиксом.

Например, LATIN1_GENERAL_100_CI_AS_SCчтобы LATIN1_GENERAL_100_CI_AS_SC_UTF8. UTF-8 доступен только для параметров сортировки Windows, которые поддерживают дополнительные символы, как это было введено в SQL Server 2012. NCHARиNVARCHAR допускают только кодировку UTF-16, и остаются без изменений.

Эта функция может обеспечить значительную экономию памяти в зависимости от используемого набора символов. Например, изменение существующего типа данных столбца со строками ASCII с NCHAR(10)на CHAR(10)использование сопоставления с поддержкой UTF-8 приводит к сокращению требований к хранилищу почти на 50%. Это сокращение связано с тем, что NCHAR(10)для хранения требуется 22 байта, тогда как CHAR(10)для той же строки Unicode требуется 12 байтов.

Обновление 2019-05-14:

Документация, похоже, сейчас обновлена ​​и объясняет наши возможности, начиная с MSSQL 2019 в разделе « Поддержка сопоставления и Unicode ».

Обновление 2019-07-24:

Статья Педро Лопеса, старшего менеджера программы в Microsoft, о введении поддержки UTF-8 для базы данных SQL Azure

Бартош X
источник
4

Обратите внимание , что по состоянию на Microsoft SQL Server 2016, UTF-8 поддерживается bcp, BULK_INSERTиOPENROWSET .

Приложение 2016-12-21: SQL Server 2016 SP1 теперь включает сжатие Unicode (и большинство других функций, которые ранее использовались только для Enterprise) для всех версий MS SQL, включая Standard и Express. Это не то же самое, что поддержка UTF-8, но дает аналогичное преимущество, если целью является сокращение дискового пространства для западных алфавитов.

Чарльз Бернс
источник
Но не ОТКРЫТОЕ ЗАПРОС? Интересно, поэтому у меня проблемы с переносом данных CLOB из Oracle с помощью OPENQUERY.
Джефф Доуди
4

Два UDF для работы с UTF-8 в T-SQL:

CREATE Function UcsToUtf8(@src nvarchar(MAX)) returns varchar(MAX) as
begin
    declare @res varchar(MAX)='', @pi char(8)='%[^'+char(0)+'-'+char(127)+']%', @i int, @j int
    select @i=patindex(@pi,@src collate Latin1_General_BIN)
    while @i>0
    begin
        select @j=unicode(substring(@src,@i,1))
        if @j<0x800     select @res=@res+left(@src,@i-1)+char((@j&1984)/64+192)+char((@j&63)+128)
        else            select @res=@res+left(@src,@i-1)+char((@j&61440)/4096+224)+char((@j&4032)/64+128)+char((@j&63)+128)
        select @src=substring(@src,@i+1,datalength(@src)-1), @i=patindex(@pi,@src collate Latin1_General_BIN)
    end
    select @res=@res+@src
    return @res
end

CREATE Function Utf8ToUcs(@src varchar(MAX)) returns nvarchar(MAX) as
begin
    declare @i int, @res nvarchar(MAX)=@src, @pi varchar(18)
    select @pi='%[à-ï][€-¿][€-¿]%',@i=patindex(@pi,@src collate Latin1_General_BIN)
    while @i>0 select @res=stuff(@res,@i,3,nchar(((ascii(substring(@src,@i,1))&31)*4096)+((ascii(substring(@src,@i+1,1))&63)*64)+(ascii(substring(@src,@i+2,1))&63))), @src=stuff(@src,@i,3,'.'), @i=patindex(@pi,@src collate Latin1_General_BIN)
    select @pi='%[Â-ß][€-¿]%',@i=patindex(@pi,@src collate Latin1_General_BIN)
    while @i>0 select @res=stuff(@res,@i,2,nchar(((ascii(substring(@src,@i,1))&31)*64)+(ascii(substring(@src,@i+1,1))&63))), @src=stuff(@src,@i,2,'.'),@i=patindex(@pi,@src collate Latin1_General_BIN)
    return @res
end
Хаби
источник