Як використовувати UTF-8 Collation у базі даних SQL Server?


83

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

Зараз я читаю /dba/7346/sql-server-2005-2008-utf-8-collation-charset, що SQL Server 2008 не підтримує utf8, це жарт?

SQL Server містить кілька баз даних, переважно кодованих латиною. Оскільки перенесена база даних призначена для публікації в Інтернеті, я хочу зберегти utf8-кодування. Я щось пропустив чи мені потрібно кодувати / відміняти на рівні програми?


Насправді немає проблем із використанням UTF8, створивши SQLCLR UDF, і ви можете завантажити з Microsoft код. перевірте це посилання: technet.microsoft.com/en-us/library/ms160893(v=sql.90).aspx
Ronen Ariely

1
Варто зазначити, що всі Java, JavaScript, DotNet та Windows використовують внутрішньо UTF-16, тому, якщо ваш веб-сайт має бути закодований в будь-якому з них, ви зберігаєте перетворення на UTF16.
Бен,

1
Якщо це допомагає, ви можете робити вигляд, що SQL Server внутрішньо зберігає текст як UTF-8; і драйвер перетворює його назад на UTF-16, коли ви отримуєте його. Ви також можете зробити вигляд, що SQL Server зберігає текст як UCS-32. Формат внутрішньої пам’яті є недоречною деталлю реалізації. Важливо те, що бази даних повертають дані символів Unicode як UTF-16 (що відповідає вашому середовищу програмування).
Ян Бойд

Відповіді:


25

Немає! Це не жарт.

Погляньте тут: 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 року.


В порядку. Чи може mssql-клієнт перекласти у зовнішній світ 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,

29

UTF-8 - це не набір символів, це кодування. Набір символів для UTF-8 - Unicode. Якщо ви хочете зберегти текст Unicode, ви використовуєте nvarcharтип даних.

Якщо база даних буде використовувати UTF-8 для зберігання тексту, ви все одно не отримаєте текст як закодовані дані UTF-8, ви отримаєте його як декодований текст.

Ви можете легко зберегти в базі даних текст, закодований UTF-8, але тоді ви не зберігаєте його як текст, а як двійкові дані ( varbinary).


Дякуємо за вступ. Тут можна більше навчитися, дивлячись, наприклад, на stackoverflow.com/questions/3951722/…
Тесон 02

Я не можу розібратися з цим. "Набір символів для UTF8 - це Unicode" ?? Чи не utf8 набагато ширший, ніж Unicode. Збереження Dauðalogn в Unicode проти utf8 дає різні результати: (EF BB BF) 44 61 75 C3 B0 61 6C 6F 67 6E проти \ u0044 \ u0061 \ u0075c \ u006f \ u0067 \ u006e
Teson

2
@ user247245: UTF-8 - це кодування, а Unicode - набір символів. UTF-8 - один із способів збереження Unicode. Те, що ви використовували для представлення Unicode, - це екранні коди, що використовуються в рядкових літералах, і зазвичай це не те, як ви представляєте Unicode як файл. UTF-32 буде найближчим перекладом безпосередньо з Uncode у формат файлу, де кожен код символу зберігається як 32-бітове число.
Guffa,

Чи можете ви пояснити, чому третя буква у наведеному вище прикладі представлена ​​в UTF8 як C3 B0, а в unicode - просто 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 для бази даних Azure SQL


4

Зверніть увагу , що за станом на Microsoft SQL Server 2016, UTF-8 підтримується bcp, BULK_INSERTі OPENROWSET.

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


Але не ВІДКРИТТЯ? Цікаво, чому саме через це у мене виникають проблеми з міграцією даних CLOB з Oracle за допомогою OPENQUERY.
Geoff Dawdy

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.