Wie verwende ich die UTF-8-Kollatierung in der SQL Server-Datenbank?

83

Ich habe eine Datenbank von MySQL auf SQL Server (Politik) migriert, die ursprüngliche MySQL-Datenbank mit UTF8.

Jetzt habe ich /dba/7346/sql-server-2005-2008-utf-8-collation-charset gelesen, dass SQL Server 2008 utf8 nicht unterstützt. Ist das ein Witz?

Der SQL Server hostet mehrere Datenbanken, die größtenteils lateinisch codiert sind. Da die migrierte Datenbank für das Web-Publishing vorgesehen ist, möchte ich die utf8-Codierung beibehalten. Habe ich etwas verpasst oder muss ich auf Anwendungsebene enc / dec?

Teson
quelle
Tatsächlich gibt es kein Problem mit der Verwendung von UTF8, indem Sie SQLCLR UDF erstellen und den Code von Microsoft herunterladen können. Überprüfen Sie diesen Link: technet.microsoft.com/en-us/library/ms160893(v=sql.90).aspx
Ronen Ariely
1
Beachten Sie, dass Java, JavaScript, DotNet und Windows UTF-16 intern verwenden. Wenn Ihre Website also in einer dieser Versionen codiert werden soll, speichern Sie eine Konvertierung in UTF16.
Ben
1
Wenn dies hilfreich ist, können Sie so tun, als würde SQL Server Text intern als UTF-8 speichern. und der Treiber konvertiert es zurück in UTF-16, wenn Sie es abrufen. Sie können auch so tun, als würde SQL Server den Text als UCS-32 speichern. Das interne Speicherformat ist ein irrelevantes Implementierungsdetail. Wichtig ist, dass Datenbanken Unicode-Zeichendaten als UTF-16 zurückgeben (passend zu Ihrer Programmierumgebung).
Ian Boyd

Antworten:

25

Nein! Es ist kein Witz.

Schauen Sie hier: http://msdn.microsoft.com/en-us/library/ms186939.aspx

Zeichendatentypen, die entweder feste Länge, nchar oder variable Länge, nvarchar, Unicode-Daten sind und den UNICODE UCS-2-Zeichensatz verwenden.

Und auch hier: http://en.wikipedia.org/wiki/UTF-16

Das ältere UCS-2 (2-Byte-Universeller Zeichensatz) ist eine ähnliche Zeichenkodierung, die im Juli 1996 in Version 2.0 des Unicode-Standards von UTF-16 abgelöst wurde.

edze
quelle
OK. Kann der mssql-Client in die externe UTF8-Welt übersetzen?
Teson
mssql-clientkann alles sein. Java, .NET, C, PHP usw. Was bedeutet Client?
Edze
1
Client: sqlsrv Erweiterung unter PHP. Robert drückt es hier als Klartext aus: social.msdn.microsoft.com/Forums/en/sqldriverforphp/thread/… wird die Ergebnisse auswerten und veröffentlichen.
Teson
2
Hallo wieder, sorry für die Verspätung , aber danke für die Wiederholungen, mit sqlsrv_connect (, array ( "CharacterSet" => "UTF-8") .. in Verbindung String funktioniert PDO ist, nicht wahr.?
Teson
29

UTF-8 ist kein Zeichensatz, sondern eine Codierung. Der Zeichensatz für UTF-8 ist Unicode. Wenn Sie Unicode-Text speichern möchten, verwenden Sie den nvarcharDatentyp.

Wenn die Datenbank UTF-8 zum Speichern von Text verwenden würde, würden Sie den Text immer noch nicht als codierte UTF-8-Daten ausgeben, sondern als decodierten Text.

Sie können UTF-8-codierten Text problemlos in der Datenbank speichern, aber dann speichern Sie ihn nicht als Text, sondern als Binärdaten ( varbinary).

Guffa
quelle
Danke für die Eingabe. Es gibt mehr zu lernen, zum Beispiel stackoverflow.com/questions/3951722/…
Teson
Ich kann mich nicht darum kümmern. "Der Zeichensatz für UTF8 ist Unicode" ?? Ist utf8 nicht viel breiter als Unicode. Das Speichern von Dauðalogn in Unicode vs utf8 führt zu unterschiedlichen Ergebnissen: (EF BB BF) 44 61 75 C3 B0 61 6C 6F 67 6E vs \ u0044 \ u0061 \ u0075 \ u00f0 \ u0061 \ u006c \ u006f \ u0067 \ u006e
Teson
2
@ user247245: UTF-8 ist die Codierung und Unicode ist der Zeichensatz. UTF-8 ist eine Möglichkeit, Unicode zu speichern. Was Sie zur Darstellung des Unicodes verwendet haben, sind Escape-Codes, die in Zeichenfolgenliteralen verwendet werden. Normalerweise stellen Sie Unicode nicht so als Datei dar. UTF-32 wäre die nächstgelegene Übersetzung direkt von Uncode in ein Dateiformat, in dem jeder Zeichencode als 32-Bit-Zahl gespeichert wird.
Guffa
Können Sie bitte erklären, warum der dritte Buchstabe im obigen Beispiel in UTF8 als C3 B0 und in Unicode einfach als F0 dargestellt wird? Danke für Ihre Hilfe.
Teson
4
@ user247245: Zeichencodes zwischen 8 und 11 Bit werden wie 110xxxxx 10xxxxxxin UTF-8 (wobei Datenbits dargestellt werden) codiert x, sodass der Zeichencode F0( 00011110000als 11 Bit) als 11000011 10110000( 00011aus dem Zeichencode im ersten Byte und 110000im zweiten Byte ) codiert wird ) was ist C3 B0.
Guffa
24

Sieht so aus, als würde dies endlich in SQL Server 2019 unterstützt! SQL Server 2019 - was ist neu?

Von BOL:

UTF-8-Unterstützung

Volle Unterstützung für die weit verbreitete UTF-8-Zeichencodierung als Import- oder Exportcodierung oder als Kollatierung auf Datenbankebene oder Spaltenebene für Textdaten. UTF-8 ist in den erlaubten CHARund VARCHARDatentypen, und aktiviert wird , wenn die Erstellung oder eines Objekts Kollation zu einer Kollation mit dem sich ändernden UTF8Suffix.

Zum Beispiel LATIN1_GENERAL_100_CI_AS_SCzu LATIN1_GENERAL_100_CI_AS_SC_UTF8. UTF-8 ist nur für Windows-Kollatierungen verfügbar, die zusätzliche Zeichen unterstützen, wie in SQL Server 2012 eingeführt, NCHARund nur NVARCHARdie UTF-16-Codierung zulassen und unverändert bleiben.

Diese Funktion kann je nach verwendetem Zeichensatz zu erheblichen Speichereinsparungen führen. Zum Beispiel kann eine bestehende Spaltendatentyp mit ASCII - Strings aus wechselnden NCHAR(10)zu CHAR(10)Verwendung einer UTF-8 aktiviert Kollation, schlägt sich in fast 50% ige Verringerung der Speicheranforderungen. Diese Reduzierung ist darauf zurückzuführen, NCHAR(10)dass für die Speicherung 22 Byte erforderlich sind, während CHAR(10)für dieselbe Unicode-Zeichenfolge 12 Byte erforderlich sind.

Update 2019-05-14:

Die Dokumentation scheint jetzt aktualisiert zu sein und erläutert unsere Optionen für MSSQL 2019 im Abschnitt " Kollatierungs- und Unicode-Unterstützung ".

Update 2019-07-24:

Artikel von Pedro Lopes - Senior Program Manager bei Microsoft über die Einführung der UTF-8-Unterstützung für die Azure SQL-Datenbank

Bartosz X.
quelle
4

Beachten Sie, dass wie von Microsoft SQL Server 2016, UTF-8 unterstützt wird bcp, BULK_INSERTund OPENROWSET.

Nachtrag 21.12.2016: SQL Server 2016 SP1 aktiviert jetzt die Unicode-Komprimierung (und die meisten anderen Funktionen, die bisher nur für Unternehmen verfügbar waren) für alle Versionen von MS SQL, einschließlich Standard und Express. Dies ist nicht dasselbe wie die UTF-8-Unterstützung, bietet jedoch einen ähnlichen Vorteil, wenn das Ziel die Reduzierung des Speicherplatzes für westliche Alphabete ist.

Charles Burns
quelle
Aber nicht OPENQUERY? Ich frage mich, ob ich aus diesem Grund Probleme beim Migrieren von CLOB-Daten von Oracle mithilfe von OPENQUERY habe.
Geoff Dawdy
4

Zwei UDF für UTF-8 in 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
Xabi
quelle