Warum sind diese Zeichen in SQL Server alle gleich?

20

Ich verstehe es einfach nicht. Siehe diese SQL-Abfrage:

select nchar(65217) -- ﻁ
select nchar(65218) -- ﻂ
select nchar(65219) -- ﻃ
select nchar(65220) -- ﻄ
if nchar(65217) = nchar(65218)
    print 'equal'
if nchar(65217) = nchar(65219)
    print 'equal'
if nchar(65217) = nchar(65220)
    print 'equal'

Basierend auf einer transitiven Beziehung bedeutet dies, dass SQL Server sie alle als dasselbe Zeichen ansieht.

In anderen Umgebungen, beispielsweise in C #, sind sie jedoch nicht identisch.

Was mich verwirrt ist:

  1. Funktionsweise des Zeichenfolgenvergleichs in SQL Server
  2. Warum sich der Vergleich nicht auf einer Maschine und einer Plattform, sondern in verschiedenen Umgebungen gleich verhält
  3. Diese 4 Zeichen stehen für ein für den Menschen verständliches Zeichen. Warum sind sie in der Unicode-Zeichentabelle so häufig?

Dies führt natürlich zu enormen Problemen, da ich an einer Textverarbeitungsanwendung arbeite und Daten fast von überall kommen und ich Text vor der Verarbeitung normalisieren muss.

Wenn ich den Grund des Unterschieds kenne, könnte ich eine Lösung finden, um damit umzugehen. Vielen Dank.

Saeed Neamati
quelle

Antworten:

28

Alle Zeichendaten in SQL Server sind mit einer Kollatierung verknüpft, die die Domäne der Zeichen bestimmt, die gespeichert werden können, sowie die Regeln, die zum Vergleichen und Sortieren von Daten verwendet werden. Die Sortierung gilt sowohl für Unicode- als auch für Nicht-Unicode-Daten.

SQL Server enthält drei große Kategorien von Kollatierungen: Binär, Legacy und Windows. Kollatierungen in der binären Kategorie ( _BINSuffix) verwenden die zugrunde liegenden Codepunkte zum Vergleichen, sodass Gleichheitsvergleiche ungleich zurückgegeben werden, wenn sich die Codepunkte unabhängig vom Zeichen unterscheiden. Legacy- ( SQL_Präfix-) und Windows-Kollatierungen bieten eine Sortier- und Vergleichssemantik für die natürlicheren Wörterbuchregeln. Dadurch können Vergleiche Groß- und Kleinschreibung, Akzente, Breite und Kana berücksichtigen. Windows-Kollatierungen bieten robustere word-sortRegeln, die eng mit dem Windows-Betriebssystem übereinstimmen, während ältere Kollatierungen nur einzelne Zeichen berücksichtigen.

Das folgende Beispiel veranschaulicht die Unterschiede zwischen Windows- und Binärsortierung mit dem Teth-Zeichen:

CREATE TABLE dbo.WindowsColationExample
    (
      Character1 nchar(1) COLLATE Arabic_100_CI_AS_SC
    , Character2 nchar(1) COLLATE Arabic_100_CI_AS_SC
    , Character3 nchar(1) COLLATE Arabic_100_CI_AS_SC
    , Character4 nchar(1) COLLATE Arabic_100_CI_AS_SC
    );

CREATE TABLE dbo.BinaryColationExample
    (
      Character1 nchar(1) COLLATE Arabic_100_BIN
    , Character2 nchar(1) COLLATE Arabic_100_BIN
    , Character3 nchar(1) COLLATE Arabic_100_BIN
    , Character4 nchar(1) COLLATE Arabic_100_BIN
    );

INSERT  INTO dbo.BinaryColationExample
VALUES  ( NCHAR(65217), NCHAR(65218), NCHAR(65219), NCHAR(65220) );
INSERT  INTO dbo.WindowsColationExample
VALUES  ( NCHAR(65217), NCHAR(65218), NCHAR(65219), NCHAR(65220) );

--all characters compare not equal
SELECT *
FROM dbo.BinaryColationExample
WHERE
    character1 = character2
    OR character1 = character3
    OR character1 = character4
    OR character2 = character3
    OR character2 = character4
    OR character3 = character4;

--all characters compare equal
SELECT *
FROM dbo.WindowsColationExample
WHERE character1 = character2;
SELECT *
FROM dbo.WindowsColationExample
WHERE character1 = character3;
SELECT *
FROM dbo.WindowsColationExample
WHERE character1 = character4;
SELECT *
FROM dbo.WindowsColationExample
WHERE character2 = character3;
SELECT *
FROM dbo.WindowsColationExample
WHERE character2 = character4;
SELECT *
FROM dbo.WindowsColationExample
WHERE character3 = character4;

Gründe, warum Unicode unterschiedliche Codepunkte für identische Glyphen enthalten kann, finden Sie unter http://en.wikipedia.org/wiki/Duplicate_characters_in_Unicode . Ich fasse zusammen, es kann aus Gründen der Legacy-Kompatibilität sein oder die Charaktere sind nicht kanonisch gleichwertig. Beachten Sie, dass das Teth-Zeichen in verschiedenen Sprachen verwendet wird ( http://en.wikipedia.org/wiki/Teth ).

Dan Guzman
quelle
15

Dies hat etwas mit COLLATIONIhrer Datenbank zu tun ( weitere Informationen in BOL ).

Ich bin mir nicht ganz sicher, in welcher Sprache das jeweilige Zeichen vorkommt, mit dem Sie ein Problem haben (ich vermute Persisch basierend auf diesem Thread), aber wenn Sie die richtige Sortierung im Gleichheitsoperator angeben, erhalten Sie genaue Ergebnisse.

if nchar(65217) COLLATE Persian_100_BIN = nchar(65218) COLLATE Persian_100_BIN 
    print 'equal'; -- nothing returned
if nchar(65217)  COLLATE Persian_100_BIN  = nchar(65217)  COLLATE Persian_100_BIN 
    print 'equal'; -- prints 'equal'
if nchar(65217) COLLATE Latin1_General_CI_AI = nchar(65220) COLLATE Latin1_General_CI_AI
    print 'equal'; -- prints 'equal'
Mark Sinkinson
quelle