Diese Frage bezieht sich nicht auf Datenbanken, sondern eher auf die Handhabung und Regeln von Unicode.
Basierend auf https://docs.microsoft.com/en-us/sql/t-sql/statements/windows-collation-name-transact-sql Latin1_General_100_CS_AS bedeutet: „Sortierungs die Latin1 Allgemeine Wörterbuch verwendet Regeln und Karten - Codepage Sortierung 1252 "mit dem zusätzlichen CS = Case Sensitive und AS = Accent Sensitive.
Die Zuordnung zwischen Windows-Codepage 1252 und Unicode ( http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT ) zeigt für alle Zeichen, mit denen wir zu tun haben, die gleichen Werte an (mit Ausnahme von e mit macron) Das gibt es in Microsoft Mapping nicht, also keine Ahnung, was es in diesem Fall tut. Daher können wir uns vorerst auf Unicode-Tools und -Terminologie konzentrieren.
Lassen Sie uns zunächst genau wissen, um was es sich bei all Ihren Saiten handelt:
0065 LATIN SMALL LETTER E
0041 LATIN CAPITAL LETTER A
00E9 LATIN SMALL LETTER E WITH ACUTE
0042 LATIN CAPITAL LETTER B
00EB LATIN SMALL LETTER E WITH DIAERESIS
0043 LATIN CAPITAL LETTER C
00E8 LATIN SMALL LETTER E WITH GRAVE
0044 LATIN CAPITAL LETTER D
00EA LATIN SMALL LETTER E WITH CIRCUMFLEX
0045 LATIN CAPITAL LETTER E
0113 LATIN SMALL LETTER E WITH MACRON
0046 LATIN CAPITAL LETTER F
Der Unicode-Kollatierungsalgorithmus wird hier beschrieben: https://www.unicode.org/reports/tr10/
Schauen Sie sich Abschnitt 1.3 "Kontextsensitivität" an, in dem erklärt wird, dass die Sortierung nicht nur von einem Zeichen nach dem anderen abhängen kann, da einige Regeln kontextsensitiv sind.
Beachten Sie auch diese Punkte in 1.8:
Kollatierung ist keine Eigenschaft von Zeichenfolgen. Die Sortierreihenfolge bleibt im Allgemeinen bei Verkettungs- oder Teilzeichenfolgenoperationen nicht erhalten.
Standardmäßig verwendet der Algorithmus drei vollständig anpassbare Ebenen. Für die lateinische Schrift entsprechen diese Ebenen ungefähr:
alphabetic ordering
diacritic ordering
case ordering.
Aber der Algorithmus an sich ist ein bisschen dicht. Das Wesentliche dabei ist: Kurz gesagt, der Unicode- Kollatierungsalgorithmus verwendet eine Eingabe-Unicode-Zeichenfolge und eine Kollatierungselementtabelle, die Zuordnungsdaten für Zeichen enthält. Es wird ein Sortierschlüssel erzeugt, bei dem es sich um ein Array von 16-Bit-Ganzzahlen ohne Vorzeichen handelt. Zwei oder mehr so erzeugte Sortierschlüssel können dann binär verglichen werden, um den richtigen Vergleich zwischen den Zeichenfolgen zu erhalten, für die sie erzeugt wurden.
Sie können die spezifischen lateinischen Sortierregeln hier anzeigen: http://developer.mimer.com/collations/charts/latin.htm
oder direkter und spezifischer für MS SQL:
http://collation-charts.org/mssql/mssql. 0409.1252.Latin1_General_CS_AS.html
Für den e
Charakter zeigt es:
e E é É è È ê Ê ë Ë
Dies erklärt Ihre Ergebnisse bei der Bestellung auf, col1
außer dass ē in Codepage 1252 nicht vorhanden ist, so dass ich absolut keine Ahnung habe, was es damit macht.
Wenn Sie den Unicode-Algorithmus von Hand ausführen, verwenden Sie den Schlüsselwert von DUCET unter http://www.unicode.org/Public/UCA/latest/allkeys.txt :
Schritt 1: Normalisierungsform D, so wird jeder Fall:
e => U+0065
é => U+0065 U+0301
ë => U+0065 U+0308
è => U+0065 U+0300
ê => U+0065 U+0302
ē => U+0065 U+0304
Schritt 2, Erstellen von Kollatierungsarrays (Nachschlagen in der Datei allkeys.txt
)
e => [.1D10.0020.0002]
é => [.1D10.0020.0002] [.0000.0024.0002]
ë => [.1D10.0020.0002] [.0000.002B.0002]
è => [.1D10.0020.0002] [.0000.0025.0002]
ê => [.1D10.0020.0002] [.0000.0027.0002]
ē => [.1D10.0020.0002] [.0000.0032.0002]
Schritt 3, Formularsortierschlüssel (für jede Ebene nehmen Sie jeden Wert in jedes Kollatierungsarray, setzen Sie dann 0000 als Trennzeichen und beginnen Sie erneut mit der nächsten Ebene)
e => 1D10 0000 0020 0000 0002
é => 1D10 0000 0020 0024 0000 0002 0002
ë => 1D10 0000 0020 002B 0000 0002 0002
è => 1D10 0000 0020 0025 0000 0002 0002
ê => 1D10 0000 0020 0027 0000 0002 0002
ē => 1D10 0000 0020 0032 0000 0002 0002
Schritt 4, Sortierschlüssel vergleichen (einfacher binärer Vergleich jedes Wertes nacheinander): Der vierte Wert reicht aus, um alle zu sortieren, sodass die endgültige Reihenfolge wie folgt lautet:
e
é
è
ê
ë
ē
In der gleichen Weise für die Bestellung auf col2
:
Schritt 1: NFD
eA => U+0065 U+0041
éB => U+0065 U+0301 U+0042
ëC => U+0065 U+0308 U+0043
èD => U+0065 U+0300 U+0044
êE => U+0065 U+0302 U+0045
ēF => U+0065 U+0304 U+0046
Schritt 2: Sortierreihen
eA => [.1D10.0020.0002] [.1CAD.0020.0008]
éB => [.1D10.0020.0002] [.0000.0024.0002] [.1CC6.0020.0008]
ëC => [.1D10.0020.0002] [.0000.002B.0002] [.1CE0.0020.0008]
èD => [.1D10.0020.0002] [.0000.0025.0002] [.1CF5.0020.0008]
êE => [.1D10.0020.0002] [.0000.0027.0002] [.1D10.0020.0008]
ēF => [.1D10.0020.0002] [.0000.0032.0002] [.1D4B.0020.0008]
Schritt 3: Formularsortierschlüssel
eA => 1D10 1CAD 0000 0020 0020 0000 0002 0008
éB => 1D10 1CC6 0000 0020 0024 0020 0000 0002 0002 0008
ëC => 1D10 1CE0 0000 0020 002B 0020 0000 0002 0002 0008
èD => 1D10 1CF5 0000 0020 0025 0020 0000 0002 0002 0008
êE => 1D10 1D10 0000 0020 0027 0020 0000 0002 0002 0008
ēF => 1D10 1D4B 0000 0020 0032 0020 0000 0002 0002 0008
Schritt 4: Sortierschlüssel vergleichen: Der zweite Wert reicht aus, um alle zu sortieren, und ist in der Tat bereits in aufsteigender Reihenfolge. Die endgültige Reihenfolge lautet also in der Tat:
eA
éB
ëC
èD
êE
ēF
Update : Hinzufügen des dritten Falles von Solomon Rutzky, der wegen des Platzes, der neue Regeln ermöglicht, schwieriger ist (ich habe den "nicht ignorierbaren Fall" gewählt):
Schritt 1, NFD:
è 1 => U+0065 U+0300 U+0020 U+0031
ê 5 => U+0065 U+0302 U+0020 U+0035
e 2 => U+0065 U+0020 U+0032
é 4 => U+0065 U+0301 U+0020 U+0034
ē 3 => U+0065 U+0304 U+0020 U+0033
ë 6 => U+0065 U+0308 U+0020 U+0036
Schritt 2, Erstellen von Kollatierungsarrays:
è 1 => [.1D10.0020.0002] [.0000.0025.0002] [*0209.0020.0002] [.1CA4.0020.0002]
ê 5 => [.1D10.0020.0002] [.0000.0027.0002] [*0209.0020.0002] [.1CA8.0020.0002]
e 2 => [.1D10.0020.0002] [*0209.0020.0002] [.1CA5.0020.0002]
é 4 => [.1D10.0020.0002] [.0000.0024.0002] [*0209.0020.0002] [.1CA7.0020.0002]
ē 3 => [.1D10.0020.0002] [.0000.0032.0002] [*0209.0020.0002] [.1CA6.0020.0002]
ë 6 => [.1D10.0020.0002] [.0000.002B.0002] [*0209.0020.0002] [.1CA9.0020.0002]
Schritt 3, Formularsortierschlüssel:
è 1 => 1D10 0209 1CA4 0000 0020 0025 0020 0020 0000 0002 0002 0002 0002
ê 5 => 1D10 0209 1CA8 0000 0020 0027 0020 0020 0000 0002 0002 0002 0002
e 2 => 1D10 0209 1CA5 0000 0020 0020 0020 0000 0002 0002 0002
é 4 => 1D10 0209 1CA7 0000 0020 0024 0020 0020 0000 0002 0002 0002 0002
ē 3 => 1D10 0209 1CA6 0000 0020 0032 0020 0020 0000 0002 0002 0002 0002
ë 6 => 1D10 0209 1CA9 0000 0020 002B 0020 0020 0000 0002 0002 0002 0002
Schritt 4, Sortierschlüssel vergleichen:
Grundsätzlich bestimmt der dritte Wert die Reihenfolge, und er basiert tatsächlich nur auf der letzten Ziffer, daher sollte die Reihenfolge folgendermaßen lauten:
è 1
e 2
ē 3
é 4
ê 5
ë 6
Zweites Update basierend auf Solomon Rutzkys Kommentar zu Unicode-Versionen.
Ich habe allkeys.txt
zu diesem Zeitpunkt die Daten der neuesten Unicode-Version verwendet, also Version 10.0
Wenn wir stattdessen Unicode 5.1 berücksichtigen müssen , wäre dies:
http://www.unicode.org/Public/UCA/5.1.0/allkeys.txt
Ich habe gerade überprüft, dass für alle oben genannten Zeichen die Sortierreihen die folgenden sind:
e => [.119D.0020.0002.0065]
é => [.119D.0020.0002.0065] [.0000.0032.0002.0301]
ë => [.119D.0020.0002.0065] [.0000.0047.0002.0308]
è => [.119D.0020.0002.0065] [.0000.0035.0002.0300]
ê => [.119D.0020.0002.0065] [.0000.003C.0002.0302]
ē => [.119D.0020.0002.0065] [.0000.005B.0002.0304]
und:
eA => [.119D.0020.0002.0065] [.1141.0020.0008.0041]
éB => [.119D.0020.0002.0065] [.0000.0032.0002.0301] [.1157.0020.0008.0042]
ëC => [.119D.0020.0002.0065] [.0000.0047.0002.0308] [.116F.0020.0008.0043]
èD => [.119D.0020.0002.0065] [.0000.0035.0002.0300] [.1182.0020.0008.0044]
êE => [.119D.0020.0002.0065] [.0000.003C.0002.0302] [.119D.0020.0008.0045]
ēF => [.119D.0020.0002.0065] [.0000.005B.0002.0304] [.11D5.0020.0008.0046]
und:
è 1 => [.119D.0020.0002.0065] [.0000.0035.0002.0300] [*0209.0020.0002.0020] [.1138.0020.0002.0031]
ê 5 => [.119D.0020.0002.0065] [.0000.003C.0002.0302] [*0209.0020.0002.0020] [.113C.0020.0002.0035]
e 2 => [.119D.0020.0002.0065] [*0209.0020.0002.0020] [.1139.0020.0002.0032]
é 4 => [.119D.0020.0002.0065] [.0000.0032.0002.0301] [*0209.0020.0002.0020] [.113B.0020.0002.0034]
ē 3 => [.119D.0020.0002.0065] [.0000.005B.0002.0304] [*0209.0020.0002.0020] [.113A.0020.0002.0033]
ë 6 => [.119D.0020.0002.0065] [.0000.0047.0002.0308] [*0209.0020.0002.0020] [.113D.0020.0002.0036]
die dann zu folgenden Sortierschlüsseln rechnen:
e => 119D 0000 0020 0000 0002 0000 0065
é => 119D 0000 0020 0032 0000 0002 0002 0000 0065 0301
ë => 119D 0000 0020 0047 0000 0002 0002 0000 0065 0308
è => 119D 0000 0020 0035 0000 0002 0002 0000 0065 0300
ê => 119D 0000 0020 003C 0000 0002 0002 0000 0065 0302
ē => 119D 0000 0020 005B 0000 0002 0002 0000 0065 0304
und:
eA => 119D 1141 0000 0020 0020 0000 0002 0008 0000 0065 0041
éB => 119D 1157 0000 0020 0032 0020 0000 0002 0002 0008 0000 0065 0301 0042
ëC => 119D 116F 0000 0020 0047 0020 0000 0002 0002 0008 0000 0065 0308 0043
èD => 119D 1182 0000 0020 0035 0020 0000 0002 0002 0008 0000 0065 0300 0044
êE => 119D 119D 0000 0020 003C 0020 0000 0002 0002 0008 0000 0065 0302 0045
ēF => 119D 11D5 0000 0020 005B 0020 0000 0002 0002 0008 0000 0065 0304 0046
und:
è 1 => 119D 0209 1138 0000 0020 0035 0020 0020 0000 0002 0002 0002 0002 0000 0065 0300 0020 0031
ê 5 => 119D 0209 113C 0000 0020 003C 0020 0020 0000 0002 0002 0002 0002 0000 0065 0302 0020 0035
e 2 => 119D 0209 1139 0000 0020 0020 0020 0000 0002 0002 0002 0000 0065 0020 0032
é 4 => 119D 0209 113B 0000 0020 0032 0020 0020 0000 0002 0002 0002 0002 0000 0065 0301 0020 0034
ē 3 => 119D 0209 113A 0000 0020 005B 0020 0020 0000 0002 0002 0002 0002 0000 0065 0304 0020 0033
ë 6 => 119D 0209 113D 0000 0020 0047 0020 0020 0000 0002 0002 0002 0002 0000 0065 0308 0020 0036
was wiederum diese drei sortierten Ergebnisse ergibt:
e
é
è
ê
ë
ē
und
eA
éB
ëC
èD
êE
ēF
und
è 1
e 2
ē 3
é 4
ê 5
ë 6
VARCHAR
(dh Nicht-Unicode-) Daten, die hier nicht verwendet werden. Das ist der Grund, warum derē
Charakter gut funktioniert. 2) Die Informationen zu "Kollatierungsdiagrammen" sind etwas veraltet. Es ist für eine frühere Version dieser Sammlung und sie haben seit 2009 nichts mehr gepostet. 3) Die Unicode-Version hier ist definitiv nicht die neueste (Version 10). Die_100_
Serien-Kollatierungen wurden mit SQL 2008 ausgeliefert, dies wäre also Unicode 5.0 oder 5.1: unicode.org/standard/versions/#TUS_Earlier_VersionsallKeys.txt
Änderungen zwischen der Unicode-Version, außer dem Hinzufügen neuer Zeichen, so dass das oben Gesagte wahr bleiben sollte, aber natürlich könnte es mit den vorherigen alten Daten wiederholt werden, mir fehlt nur die Energie, einige Stunden erneut hinein zu stecken. Der CP1252 stammt nur aus der Definition von MS-SQL (ich verwende dieses Produkt nicht selbst).Das Verhalten, das Sie hier sehen, ist im Allgemeinen auf die Tatsache zurückzuführen, dass der Unicode-Kollatierungsalgorithmus (Unicode Collation Algorithm, UCA) eine komplexe mehrstufige Sortierung ermöglicht. Genauer:
Sortieren ist kein Vergleich:
Es ist ziemlich einfach zu bestimmen, ob zwei Zeichenfolgen gleich oder verschieden sind (unter Berücksichtigung eines bestimmten Gebietsschemas / einer bestimmten Sprache und einer Reihe von Empfindlichkeiten). Die Bestimmung der Reihenfolge von zwei oder mehr Zeichenfolgen kann jedoch sehr komplex sein.
Die Sortierung erfolgt in einer Reihe von Schritten, wobei jeder Schritt auf die gesamte Zeichenfolge angewendet wird und nicht zeichenweise:
Wenn Sie nach
col1
(einzelnes Zeichen) sortieren , wird zuerst festgestellt, dass alle Zeichen dasselbe Gewicht haben, da sie alle " e " sind. Als nächstes werden die Akzent- / diakritischen Gewichte angewendet. Es gibt keine Unterschiede in der Gehäuseform, sodass der dritte Schritt nichts ändern würde. Die einzigen Unterschiede bestehen also in Schritt 2, weshalb es für diese Zeilen eine bevorzugte Reihenfolge gibt, die auf basiertcol1
.Wenn Sie nach
col2
(zwei Zeichen) sortieren , wird zunächst festgestellt, dass jede Zeile ein unterschiedliches Gewicht hat, da beide Zeichen zum Bestimmen des Sortiergewichts verwendet werden (z. B. " ea ", " eb " usw.). Als nächstes werden die Akzent- / diakritischen Gewichte angewendet. Es gibt keine Unterschiede in der Gehäuseform, sodass der dritte Schritt nichts ändern würde. Diesmal gibt es also Unterschiede in den Schritten 1 und 2. Da die Unterschiede in Schritt 1 jedoch bereits auf jede Zeichenfolge angewendet wurden, bevor die Gewichte von Schritt 2 berücksichtigt wurden, haben die Gewichte aus Schritt 2 keine Auswirkungen auf die Reihenfolge. Sie gelten nur, wenn die Gewichte aus Schritt 1 für zwei oder mehr Zeilen gleich sind.Die folgende Anpassung des Beispielcodes aus der Frage veranschaulicht hoffentlich das oben beschriebene Sortierverhalten. Ich habe einige zusätzliche Zeilen und eine zusätzliche Spalte hinzugefügt, um zu veranschaulichen, wie sich die Sortierung auf die Groß- und Kleinschreibung auswirkt (da die ursprünglichen Beispieldaten nur Kleinbuchstaben enthalten):
INSTALLIEREN
TEST 1
Kehrt zurück:
Was wir in den Ergebnissen oben sehen können:
TEST 2
Kehrt zurück:
Was wir in den Ergebnissen oben sehen können:
TEST 3
Kehrt zurück:
Was wir in den Ergebnissen oben sehen können:
col2
in der Frage wieder auf "Mehrstufiger Vergleich" und nicht auf "Kontextsensitivität" zurückzuführen ist.Zusätzliche Bemerkungen:
Bezüglich der genauen Regeln ist das nicht so einfach, wie es sein sollte. Das Problem beim Abrufen konkreter Erklärungen zu diesen Regeln besteht darin, dass die Unicode-Sortierregeln, obwohl sie eindeutig dokumentiert sind, eine Empfehlung darstellen. Es liegt an Anbietern wie Microsoft, diese Empfehlungen umzusetzen. Microsoft hat die Empfehlungen nicht genau so implementiert, wie in der Unicode-Dokumentation angegeben, sodass es dort zu einer Unterbrechung kommt (ähnlich wie weder die HTML- noch die CSS-Spezifikationen von Anbietern vollständig noch auf dieselbe Weise implementiert werden). Dann gibt es verschiedene Versionen der Windows-Kollatierungen (Sie verwenden
100
die mit SQL Server 2008 gelieferte Version), die an eine Unicode-Version gebunden sind, die viel älter ist als die aktuelle Unicode-Version oder die Version, die verwendet ICU-Kollatierungsdemobenutzt. DerNeuerungen in SQL Server 2008-Kollatierungen Der Abschnitt "Kollatierungs- und Unicode-Unterstützung" in der Dokumentation zu SQL Server 2008 enthält zwei sehr interessante Punkte zu den Neuerungen in der_100_
Reihe "Kollatierungen":Unicode 5.0 wurde im Juli 2006 veröffentlicht (nun, die Charakterdatenbank wurde dann veröffentlicht und die vollständige Spezifikation folgte Ende 2006). Die aktuelle Version ist 10.0 und wurde im Juni 2017 veröffentlicht. Angesichts des Veröffentlichungsmusters der letzten 4 Jahre ist es wahrscheinlich, dass die Version 11.0 Mitte 2018 veröffentlicht wird.
Diese Gewichte wurden höchstwahrscheinlich im Unicode-Standard definiert, jedoch nicht in dieser Implementierung.
Die oben verlinkte UCA-Dokumentation ist dennoch ein guter Ausgangspunkt.
Sortierschlüssel, die von Windows / .NET / SQL Server verwendet werden, stimmen nicht genau mit denen überein, die im Unicode-Standard (siehe @ Patricks Antwort) oder auf der Intensivstation implementiert sind . Mit der CompareInfo.GetSortKey-Methode können Sie die Verwendung von Windows / .NET / SQL Server überprüfen . Ich habe eine SQLCLR-UDF erstellt, um diese Werte zu übergeben und den Sortierschlüssel zu erhalten. Bitte beachten Sie, dass ich SQL Server 2017 unter Windows 10 mit installiertem .NET Framework 4.5 - 4.6.1 verwende. Daher sollte .NET Unicode 6.0.0 verwenden. Außerdem wird Level4 für diese Zeichenfolgen nicht verwendet.
Wenn Sie sich diese Sortierschlüssel für Test 1 ansehen und feststellen, dass die Ebenen in einer
ORDER BY
Klausel wie mehrere Spalten sortiert sind (L3 wird in denselben Werten von L2 sortiert, die in denselben Werten von L1 sortiert sind), sollte dies den Grund für das Verhalten verdeutlichen In der Frage ist in der Tat die mehrstufige Sortierfähigkeit von Unicode vermerkt. Gleichfalls:Wenn wir uns einige der Sortierschlüssel für Test 2 ansehen, sehen wir, dass die Basiszeichen zuerst sortiert werden (L1), dann die Akzente sortiert werden (L2) und dann die Groß- / Kleinschreibung sortiert wird (L3).
Da es sich bei dem Datentyp
NVARCHAR
um Unicode-Codepunkte und Sortieralgorithmen handelt, wird dieUNICODE()
Funktion in TEST 1 verwendet. Codepages werden zwar von den meisten Sortierungen angegeben, beziehen sich jedoch nur aufVARCHAR
Daten. Das heißt, während Codepage 1252 durch dieLatin1_General*
Reihe der Kollatierungen angegeben wird, kann dies hier ignoriert werden.Die in der Standard-Unicode-Kollatierungselementtabelle (DUCET) ( Version 5.0.0, die den
_100_
Serienkollatierungen entsprechen sollte ) beschriebenen Gewichtungen sind für US-Englisch in Ordnung, jedoch nicht für andere Gebietsschemata / Sprachen. Andere Sprachen müssen beginnen mit dem Ducet und dann gelten länderspezifische Überschreibung Regeln wie definiert durch die Common Locale Data Repository (CLDR) Projekt. Soweit ich weiß, wurden die Versionen 1.4 / 1.4.1 im Jahr 2006 veröffentlicht. Um diese Außerkraftsetzungen zu erhalten, laden Sie die "Core" -Datei für CLDR 1.4 über http://unicode.org/Public/cldr/1.4.0/core.zip herunter Wechseln Sie dann in dieser ZIP-Datei zum Kollatierungsordner und suchen Sie die XML-Datei, die dem verwendeten Gebietsschema entspricht. Diese Dateien enthalten nur die Außerkraftsetzungen und sind keine vollständigen Sätze von Kollatierungsregeln.quelle