Ich möchte eine Unicode-Zeichenfolgenvariable basierend auf ihrem Unicode-Codepunkt auf ein bestimmtes Zeichen festlegen.
Ich möchte einen Codepunkt jenseits von 65535 verwenden, aber die SQL Server 2008 R2-Datenbank hat eine Sortierung von SQL_Latin1_General_CP1_CI_AS
.
Gemäß der NCHAR-Dokumentation von Microsoft nimmt die NCHAR
Funktion eine Ganzzahl wie folgt an:
integer_expression
Wenn die Sortierung der Datenbank nicht das Zusatzzeichen (SC) enthält, ist dies eine positive ganze Zahl von 0 bis 65535 (0 bis 0xFFFF). Wenn ein Wert außerhalb dieses Bereichs angegeben wird, wird NULL zurückgegeben. Weitere Informationen zu zusätzlichen Zeichen finden Sie unter Sortierung und Unicode-Unterstützung.
Wenn die Sortierung der Datenbank das Zusatzzeichen (SC) -Flag unterstützt, ist dies eine positive ganze Zahl von 0 bis 1114111 (0 bis 0x10FFFF). Wenn ein Wert außerhalb dieses Bereichs angegeben wird, wird NULL zurückgegeben.
Also dieser Code:
SELECT NCHAR(128512);
Gibt NULL
in dieser Datenbank zurück.
Ich würde es gerne so zurückgeben:
SELECT N'😀';
Wie kann ich eine Unicode-Zeichenfolgenvariable (z. B. nvarchar) mithilfe von Code (ohne Verwendung des eigentlichen Emoji-Zeichens) in einer Datenbank, in der die Kollatierung "kein SC-Flag (Additional Character) enthält", auf ein Emoji setzen?
Vollständige Liste der Emoji-Unicode-Codepunkte
(Letztendlich möchte ich, dass jeder Charakter funktioniert. Ich habe mich für Emoji entschieden, um das Nachschlagen zu erleichtern.)
(Obwohl der Server SQL Server 2008 R2 ist, bin ich auch neugierig auf Lösungen für spätere Versionen.)
Unter der Annahme, dass es keinen Weg gibt, könnte ich auf eine benutzerdefinierte Inline-Funktion in einer anderen Datenbank verweisen, die über eine geeignete Kollatierung verfügt?
Wie finde ich eine Kollatierung mit dem Zusatzzeichen?
Dies gibt keine Datensätze auf unserem Server zurück:
SELECT * FROM sys.fn_helpcollations()
WHERE name LIKE 'SQL%[_]SC';
Offenbar wurde SQL Server 2012 eingeführt, Latin1_General_100_CI_AS_SC
das funktionieren würde. Können Sie Kollatierungen auf älteren Instanzen installieren?
Kollatierungsreferenzen:
- Antwort auf Was ist der Unterschied zwischen char, nchar, varchar und nvarchar in SQL Server?
- Sortierinformation für Microsoft-Ergänzungszeichen
- Microsoft SQL Server 2008 R2-Kollatierungsliste
Gibt es eine Erklärung dafür, warum SQL Server unabhängig von der Sortierung die erweiterten Zeichen verstehen und damit umgehen kann, außer aus der Perspektive von NCHAR
?
Antworten:
Die UCS-2-Codierung besteht immer aus 2 Bytes pro Zeichen und hat einen Bereich von 0 bis 65535 (0x0000 bis 0xFFFF). UTF-16 (unabhängig von Big Endian oder Little Endian) hat einen Bereich von 0 - 1114111 (0x0000 - 0x10FFFF). Der Bereich 0 - 65535 / 0x0000 - 0xFFFF von UTF-16 beträgt 2 Byte pro Zeichen, während der Bereich über 65536 / 0xFFFF 4 Byte pro Zeichen beträgt.
Windows und SQL Server verwendeten zunächst die UCS-2-Codierung, da diese verfügbar war und UTF-16 noch nicht finalisiert wurde. Glücklicherweise gab es in den Entwürfen von UCS-2 und UTF-16 genügend Voraussicht, dass die UCS-2-Zuordnungen eine vollständige Teilmenge der UTF-16-Zuordnungen darstellen (dh der Bereich 0 - 65535 / 0x0000 - 0xFFFF) von UTF-16 ist UCS-2). AND, der Bereich 65536 - 1114111 (0x10000 - 0x10FFFF) von UTF-16 wird aus zwei Codepunkten im UCS-2-Bereich (Bereiche 0xD800 - 0xDBFF und 0xDC00 - 0xDFFF, speziell) erstellt, die für diesen Zweck reserviert wurden und ansonsten keine haben Bedeutung. Diese Kombination von zwei Codepunkten wird als Ersatzpaar bezeichnet, und Ersatzpaare stehen für Zeichen außerhalb des UCS-2-Bereichs, die als Zusatzzeichen bezeichnet werden.
All diese Informationen erläutern zwei Aspekte von
NVARCHAR
/ Unicode-Daten in SQL Server:NCHAR()
) nicht Surrogate Pairs / Ergänzende Zeichen behandeln , wenn kein zusätzlichen Charakter-Aware Sortierungs mit (SCA, dh einer mit_SC
, oder_140_
aber nicht_BIN*
im Namen) , weil das Nicht-SCA Sortierungen (vor allem derSQL_
Kollatierungen) wurden ursprünglich implementiert, bevor UTF-16 abgeschlossen wurde (irgendwann im Jahr 2000, glaube ich). Die Nicht-SQL_
Kollatierungen, die_90_
oder_100_
in ihren Namen enthalten sind, jedoch keine_SC
minimale Unterstützung für Zusatzzeichen in Bezug auf Vergleich und Sortierung aufweisen.NVARCHAR
/NCHAR
/XML
/NTEXT
Datentypen , weil UCS-2 und UTF-16 exakt die gleichen Byte - Sequenzen sind. Der einzige Unterschied besteht darin, dass UTF-16 die Ersatzcodepunkte verwendet, um Ersatzpaare zu erstellen, und UCS-2 kann sie einfach keinen Zeichen zuordnen. Daher werden sie den integrierten Funktionen als zwei unbekannte Zeichen angezeigt.Vor diesem Hintergrund können wir nun die spezifischen Fragen durchgehen:
Dies kann nur passieren, wenn die aktuelle Datenbank, in der die Abfrage ausgeführt wird, eine Standardkollation hat, die Supplementary Character-Aware ist und die in SQL Server 2012 eingeführt wurde. Für integrierte Funktionen mit Zeichenfolge-Eingabeparametern kann die Kollation bereitgestellt werden inline über die
COLLATE
Klausel (dhLEN(N'string' COLLATE Some_Collation_SC)
) und nicht müssen innerhalb einer Datenbank ausgeführt werden , die eine SCA Standardkollatierung hat. Integrierte Funktionen wie dasNCHAR()
Akzeptieren einesINT
Eingabeparameters und dieCOLLATE
Klausel sind in diesem Kontext jedoch nicht gültig (weshalbNCHAR()
nur Zusatzzeichen unterstützt werden, wenn in der aktuellen Datenbank eine Standardkollatierung vorhanden ist, die Supplementary Character-Aware ist. Dies ist jedoch nicht erforderlich Unannehmlichkeiten, die geändert werden können, also stimmen Sie für meinen Vorschlag ab:Die Funktion NCHAR () sollte unabhängig von der Standardkollatierung der aktiven Datenbank immer ein Ergänzungszeichen für die Werte 0x10000 - 0x10FFFF zurückgeben .Wie SQL Server zusätzliche Zeichen ohne Datenverlust speichern und abrufen kann, wurde im oberen Abschnitt dieser Antwort erläutert. Es ist jedoch nicht wahr, dass dies
NCHAR
die einzige integrierte Funktion ist, bei der Probleme mit zusätzlichen Zeichen auftreten (wenn keine SCA-Kollatierung verwendet wird). Gibt beispielsweise denLEN(N'😀' COLLATE SQL_Latin1_General_CP1_CI_AS)
Wert 2 und denLEN(N'😀' COLLATE Latin1_General_100_CI_AS_SC)
Wert 1 zurück.Wenn Sie zu dem in der Frage angegebenen zweiten Link gehen (z. B. "Microsoft's Supplementary Characters Collation Information") und ein wenig nach unten scrollen, sehen Sie ein Diagramm der integrierten Funktionen und wie sie sich basierend auf der effektiven Kollatierung verhalten.
In einer Version von SQL Server vor 2012 ist dies nicht möglich. Ab SQL Server 2012 können Sie jedoch die folgende Abfrage verwenden:
Ihre Abfrage war in der Nähe, aber das Muster, mit dem begonnen wurde,
SQL
und die SQL Server-Kollatierungen (dh die Kollatierungen, die mit beginnenSQL_
) wurden für eine Weile zugunsten der Windows-Kollatierungen (die nicht mit beginnenSQL_
) verworfen . Daher werden dieSQL_
Kollatierungen nicht aktualisiert und haben daher keine neueren Versionen, die diese_SC
Option enthalten würden (und ab SQL Server 2017 unterstützen alle neuen Kollatierungen automatisch zusätzliche Zeichen und benötigen oder haben nicht das_SC
Flag und ja, die Abfrage Die direkt darüber angezeigten Konten berücksichtigen dies und_UTF8
greifen die in SQL Server 2019 hinzugefügten Kollatierungen auf.Nein, Sie können Collations nicht in einer früheren Version von SQL Server installieren.
Wenn Sie keine SCA-Kollatierung verwenden, können Sie Codepunkte über 65535 / U + FFFF auf zwei Arten einfügen:
NCHAR()
Funktion mit jeweils einem Teil des Paars anVARBINARY
Form der Little-Endian-Bytefolge (dh der umgekehrten Bytefolge) zu konvertieren .Diese beiden Methoden zum Einfügen von Ergänzungszeichen / Ersatzpaaren funktionieren auch dann, wenn die effektive Kollatierung sich der ergänzenden Zeichen bewusst ist, und sollten in allen Versionen von SQL Server mindestens bis 2005 gleich funktionieren (obwohl dies wahrscheinlich auch in funktionieren würde Auch SQL Server 2000).
Beispiel:
💩
AKTUALISIEREN
Sie können den folgenden iTVF verwenden, um die Ersatzpaarwerte (in beiden
INT
und inBINARY
Form) von einem beliebigen Codepunkt zwischen 65536 - 1114111 (0x010000 - 0x10FFFF) abzurufen. Und während der Eingabeparameter vom Typ istINT
, können Sie die Binär- / Hexadezimalform des Codepunkts übergeben, und er wird implizit in den richtigen ganzzahligen Wert konvertiert.Mit der obigen Funktion werden die folgenden zwei Abfragen ausgeführt:
beide geben Folgendes zurück:
UPDATE 2: Ein noch besseres Update!
Ich habe die oben gezeigte iTVF so angepasst, dass sie jetzt 188.657 Codepunkte zurückgibt, sodass Sie keinen bestimmten Wert anpassen müssen. Als TVF können Sie natürlich eine
WHERE
Klausel hinzufügen , um nach einem bestimmten Codepunkt oder einem Bereich von Codepunkten oder "ähnlichen Zeichen" usw. zu filtern. Außerdem enthält sie zusätzliche Spalten mit vorformatierten Escape-Sequenzen, um jeden Code zu erstellen point (sowohl BMP- als auch Zusatzzeichen) in T-SQL, HTML und C-Style (dh\xHHHH
). Lesen Sie hier alles darüber:SSMS-Tipp 3: Einfacher Zugriff auf ALLE Unicode-Zeichen (Ja, einschließlich Emojis 😸)
quelle