Wie funktioniert die Sortierung ohne Berücksichtigung der Groß- / Kleinschreibung?

19

Der standardmäßige Sortierungstyp in SQL Server ermöglicht die Indizierung von Zeichenfolgen, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird, wobei die Groß- und Kleinschreibung der Daten beibehalten wird. Wie funktioniert das eigentlich? Ich suche nach den richtigen Schrauben und Muttern, nach Bits und Bytes oder nach einer guten Ressource, die es ausführlich erklärt.

create table casetest (fruitnames nvarchar(50) not null);
create unique index IX_fruitnames on casetest(fruitnames);

insert into casetest values ('apples');
insert into casetest values ('Pears');
-- this insert fails
insert into casetest values ('pears');

-- this yields 'Pears' as a result
select * from casetest (forceseek) where fruitnames = 'PEARS'

update casetest set fruitnames = 'pears' where fruitnames = 'pEArs'

-- this yields 'pears' as a result
select * from casetest (forceseek) where fruitnames = 'PEARS'

Fragen zu SQL Server-Kollatierungen, die Sie zu schüchtern gestellt haben Robert Sheldon behandelt die Verwendung der Kollatierung. Es wird nicht behandelt, wie die Sortierung funktioniert. Ich bin daran interessiert, wie ein Index effizient erstellt / abgefragt werden kann, ohne sich um den Fall zu kümmern, während gleichzeitig Falldaten gespeichert werden.

Cocogorilla
quelle
1
Sie können Zeichenfolgen, bei denen die Groß- / Kleinschreibung nicht beachtet wird, effizient abfragen (z. B. mithilfe einer Indexsuche). Dies ist jedoch etwas ärgerlich .
John Eisbrener
cocogorilla: Bitte beachten Sie die Anmerkung Nr. 1, die ich gerade am Ende meiner Antwort hinzugefügt habe, bezüglich der "Standard" -Kollatierung.
Solomon Rutzky

Antworten:

26

Indizierung gegen Zeichenfolgen, bei denen die Groß- und Kleinschreibung nicht beachtet wird. Die Groß- und Kleinschreibung der Daten wird jedoch beibehalten. Wie funktioniert das eigentlich?

Dies ist eigentlich kein SQL Server-spezifisches Verhalten, es ist nur so, wie diese Dinge im Allgemeinen funktionieren.

Die Daten sind also die Daten. Wenn Sie speziell über einen Index sprechen, die Daten müssen gespeichert werden , wie es ist , sonst wäre es eine Nachschau in der Haupttabelle jedes Mal benötigt den tatsächlichen Wert zu erhalten, und es gäbe keine Möglichkeit einen abdeckenden Index (zumin zumindest nicht für String-Typen).

Die Daten, die entweder in der Tabelle / gruppierten Index oder nicht gruppierten Index, sind nicht enthalten jede Kollation / Sortieranlagen info. Es sind einfach Daten. Die Sortierung (Gebietsschema / Kulturregeln und Sensitivitäten) besteht nur aus Metadaten, die an die Spalte angehängt sind und verwendet werden, wenn eine Sortieroperation aufgerufen wird (sofern sie nicht von einem überschrieben wird)COLLATEKlausel), die die Erstellung / Neuerstellung eines Indexes umfassen würde. Die durch eine nicht-binäre Kollatierung definierten Regeln werden verwendet, um Sortierschlüssel zu generieren, die binäre Darstellungen der Zeichenfolge sind (Sortierschlüssel sind in binären Kollatierungen nicht erforderlich). Diese binären Darstellungen enthalten alle Regeln für das Gebietsschema / die Kultur und ausgewählte Empfindlichkeiten. Die Sortierschlüssel werden verwendet, um die Datensätze in der richtigen Reihenfolge zu platzieren, werden jedoch nicht selbst im Index oder in der Tabelle gespeichert. Sie werden nicht gespeichert (zumindest habe ich diese Werte nicht im Index gesehen und wurde darüber informiert, dass sie nicht gespeichert werden), weil:

  1. Sie werden für die Sortierung nicht wirklich benötigt, da sie ohnehin nur in derselben Reihenfolge wie die Zeilen in der Tabelle oder im Index vorliegen würden. Die physische Reihenfolge des Indexes ist jedoch nur Sortieren, nicht Vergleichen.
  2. Während das Speichern die Vergleiche beschleunigt, vergrößert sich der Index, da die Mindestgröße für ein einzelnes Zeichen 5 Byte beträgt, und das ist nur "Overhead" (der Sortierschlüsselstruktur). Die meisten Zeichen bestehen aus jeweils 2 Byte plus 1 Byte, wenn ein Akzent vorhanden ist, plus 1 Byte, wenn es sich um Großbuchstaben handelt. Beispielsweise ist "e" ein 7-Byte-Schlüssel, "E" und "é" sind beide 8 Byte und "É" ist ein 9-Byte-Schlüssel. Daher lohnt es sich nicht, diese am Ende zu speichern.

Es gibt zwei Arten von Kollatierungen: SQL Server und Windows.

SQL Server

SQL Server-Kollatierungen (mit Namen, die mit beginnen SQL_) sind die älteren Sortier- / Vergleichsmethoden vor SQL Server 2000 (obwohl dies unter US-englischen Betriebssystemen leider SQL_Latin1_General_CP1_CI_ASimmer noch die Standardinstallation ist). In diesem älteren, vereinfachten Nicht-Unicode-Modell wird jeder Kombination aus Gebietsschema, Codepage und den verschiedenen Empfindlichkeiten eine statische Zuordnung der einzelnen Zeichen in dieser Codepage gegeben. Jedem Zeichen wird ein Wert (dh ein Sortiergewicht) zugewiesen, der angibt, wie es mit den anderen Zeichen gleichgesetzt wird. Vergleiche in diesem Modell scheinen eine Operation mit zwei Durchläufen durchzuführen:

  1. Zuerst werden alle Akzente entfernt (so dass "  ü  " zu "  u  " wird), Zeichen wie "  Æ  " zu "  A  " und "  E  " erweitert und dann eine erste Sortierung durchgeführt, sodass die Wörter in einer natürlichen Reihenfolge sind (wie Sie es tun würden) erwarten, sie in einem Wörterbuch zu finden).
  2. Dann wird Zeichen für Zeichen die Gleichheit anhand dieser zugrunde liegenden Werte für jedes Zeichen ermittelt. Dieser zweite Teil beschreibt mustaccio in seiner Antwort .

Die einzigen Empfindlichkeiten, die in diesen Kollatierungen eingestellt werden können, sind: "case" und "accent" ("width", "kana type" und "variant selector" sind nicht verfügbar). Außerdem unterstützt keine dieser Kollatierungen zusätzliche Zeichen (was sinnvoll ist, da diese Unicode-spezifisch sind und diese Kollatierungen nur für Nicht-Unicode-Daten gelten).

Dieser Ansatz gilt nur für Nicht-Unicode- VARCHARDaten. Jede eindeutige Kombination aus Gebietsschema, Codepage, Groß- und Kleinschreibung und Akzentabhängigkeit verfügt über eine bestimmte "Sortier-ID", die Sie im folgenden Beispiel sehen können:

SELECT COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CI_AS', 'SortID'), -- 52
       COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CS_AS', 'SortID'), -- 51
       COLLATIONPROPERTY(N'Latin1_General_100_CI_AS',     'SortID'); --  0

Der einzige Unterschied zwischen den ersten beiden Kollatierungen ist die Groß- und Kleinschreibung. Die dritte Kollatierung ist eine Windows-Kollatierung und verfügt daher nicht über eine statische Zuordnungstabelle.

Außerdem sollten diese Sortierungen schneller als die Windows-Sortierungen sortiert und verglichen werden, da einfach nach Zeichen gesucht wird, um die Gewichtung zu sortieren. Diese Kollatierungen sind jedoch auch weitaus weniger funktional und sollten im Allgemeinen nach Möglichkeit vermieden werden.

Windows

Windows-Kollatierungen (solche mit Namen, die nicht mit beginnen SQL_) sind die neueren Sortier- / Vergleichsmethoden (ab SQL Server 2000). In diesem neueren, komplexen Unicode-Modell wird jeder Kombination aus Gebietsschema, Codepage und den verschiedenen Empfindlichkeiten keine statische Zuordnung zugewiesen. Zum einen gibt es in diesem Modell keine Codepages. Dieses Modell weist jedem Zeichen einen Standardsortierwert zu. Anschließend kann jedes Gebietsschema / jede Kultur jeder beliebigen Anzahl von Zeichen Sortierwerte zuweisen. Auf diese Weise können mehrere Kulturen dieselben Zeichen auf unterschiedliche Weise verwenden. Dies hat den Effekt, dass mehrere Sprachen auf natürliche Weise mit derselben Sortierung sortiert werden können, wenn sie nicht dieselben Zeichen verwenden (und wenn einer von ihnen keine Werte neu zuweisen muss und einfach die Standardwerte verwenden kann).

Die Sortierwerte in diesem Modell sind keine Einzelwerte. Sie sind ein Array von Werten, die dem Basisbuchstaben, diakritischen Zeichen (dh Akzenten), Groß- und Kleinschreibung usw. relative Gewichte zuweisen. Wenn bei der Kollatierung die Groß- und Kleinschreibung beachtet wird, wird der Teil "case" dieses Arrays verwendet, andernfalls wird er ignoriert ( daher unempfindlich). Wenn die Sortierung akzentabhängig ist, wird der "diakritische" Teil des Arrays verwendet, andernfalls wird er ignoriert (daher unempfindlich).

Vergleiche in diesem Modell sind eine Operation mit mehreren Durchläufen:

  1. Zunächst wird die Zeichenfolge normalisiert, sodass verschiedene Darstellungsweisen für dasselbe Zeichen gleich sind. Beispielsweise könnte " ü " ein einzelnes Zeichen / Code-Punkt (U + 00FC) sein. Sie können auch ein nicht akzentuiertes " u " (U + 0075) mit einer kombinierten Diaeresis " ̈ " (U + 0308) kombinieren , um Folgendes zu erhalten: " ü ", das nicht nur beim Rendern gleich aussieht (es sei denn, es liegt ein Problem mit vor) Ihre Schriftart), wird aber auch als dieselbe wie die Einzelzeichenversion (U + 00FC) angesehen, sofern keine binäre Kollatierung verwendet wird (die Bytes anstelle von Zeichen vergleicht). Bei der Normalisierung wird das einzelne Zeichen in verschiedene Teile aufgeteilt, einschließlich der Erweiterungen für Zeichen wie "  Æ  " (wie oben für SQL Server-Kollatierungen angegeben).
  2. Die Vergleichsoperation in diesem Modell erfolgt zeichenweise für jede Empfindlichkeit . Sortierschlüssel für die Zeichenfolgen werden durch Anwenden der entsprechenden Elemente der Sortierreihenfolge der einzelnen Zeichen von Werten bestimmt, auf deren Grundlage die Empfindlichkeiten "empfindlich" sind. Die Sortierschlüsselwerte sind nach allen primären Empfindlichkeiten jedes Zeichens (dem Basiszeichen), gefolgt von allen sekundären Empfindlichkeiten (diakritischem Gewicht), gefolgt von dem Fallgewicht jedes Zeichens usw. angeordnet.
  3. Die Sortierung erfolgt anhand der berechneten Sortierschlüssel. Mit jeder Sensitivität, die in Gruppen zusammengefasst ist, können Sie beim Vergleichen von Zeichenfolgen mit mehreren Zeichen eine andere Sortierreihenfolge erhalten als mit einer entsprechenden SQL Server-Kollatierung. Dabei handelt es sich um Akzente auch Groß- und Kleinschreibung beachten).

Weitere Einzelheiten zu dieser Sortierung, werde ich veröffentlichen schließlich einen Beitrag , dass zeigt die Sortierschlüsselwerte, wie sie berechnet werden, die Unterschiede zwischen SQL Server und Windows - Sortierungen etc. Aber jetzt bitte meine Antwort sehen: Accent Sensitive Sort ( Bitte beachten Sie, dass die andere Antwort auf diese Frage eine gute Erklärung des offiziellen Unicode-Algorithmus ist, SQL Server jedoch stattdessen einen benutzerdefinierten, wenn auch ähnlichen Algorithmus und sogar eine benutzerdefinierte Gewichtstabelle verwendet.

In diesen Kollatierungen können alle Empfindlichkeiten angepasst werden: "Groß- / Kleinschreibung", "Akzent", "Breite", "Kana-Typ" und "Variationsauswahl" (ab SQL Server 2017 und nur für japanische Kollatierungen). Außerdem unterstützen einige dieser Sortierungen (bei Verwendung mit Unicode-Daten) zusätzliche Zeichen (ab SQL Server 2012). Dieser Ansatz gilt für beide NVARCHAR und VARCHAR Daten (auch Nicht-Unicode - Daten). Dies gilt für Nicht-Unicode- VARCHARDaten, indem zunächst der Wert intern in Unicode konvertiert und anschließend die Sortier- / Vergleichsregeln angewendet werden.


Bitte beachten Sie:

  1. Es gibt keine universelle Standardkollatierung für SQL Server. Es gibt einen Installationsstandard, der sich basierend auf der aktuellen Ländereinstellung / Spracheinstellung des Betriebssystems zum Zeitpunkt der Installation unterscheidet (was leider SQL_Latin1_General_CP1_CI_ASfür US-englische Systeme gilt, stimmen Sie also für diesen Vorschlag ab ). Dies kann während der Installation geändert werden. Diese Kollatierung auf Instanzebene legt dann die Kollatierung für die [model]Datenbank fest, die beim Erstellen neuer DBs als Vorlage verwendet wird. Die Kollatierung kann jedoch bei der Ausführung CREATE DATABASEdurch Angabe der COLLATEKlausel geändert werden . Diese Kollatierung auf Datenbankebene wird für Variablen- und Zeichenfolgenliterale sowie für neue (und geänderte!) Spalten verwendet, wenn die COLLATEKlausel nicht angegeben ist (was für den Beispielcode in der Frage der Fall ist).
  2. Weitere Informationen zu Kollatierungen / Kodierungen / Unicode finden Sie unter: Kollatierungsinformationen
Solomon Rutzky
quelle
5

In der Regel wird dies mithilfe von Sortiertabellen implementiert, die jedem Zeichen eine bestimmte Punktzahl zuweisen. Die Sortierroutine verfügt über einen Komparator, der eine geeignete Tabelle verwendet, ob standardmäßig oder explizit angegeben, um Zeichenfolgen zeichenweise anhand ihrer Sortierergebnisse zu vergleichen. Wenn beispielsweise eine bestimmte Sortiertabelle eine Bewertung von 1 bis "a" und 201 bis "A" zuweist und eine niedrigere Bewertung in dieser bestimmten Implementierung eine höhere Priorität bedeutet, wird "a" vor "A" sortiert. Eine andere Tabelle weist möglicherweise umgekehrte Bewertungen zu: 201 bis "a" und 1 bis "A", und die Sortierreihenfolge wird anschließend umgekehrt. Noch eine andere Tabelle könnte "a", "A", "Á" und "Å" gleiche Werte zuweisen, was zu einem Vergleich und einer Sortierung führen würde, bei denen die Groß- und Kleinschreibung nicht beachtet wird.

In ähnlicher Weise wird ein solcher auf einer Kollationstabelle basierender Komparator verwendet, wenn ein Indexschlüssel mit dem im Prädikat angegebenen Wert verglichen wird.

mustaccio
quelle
1
Nur zu Ihrer Information: Diese Informationen sind nur in Bezug auf die Verwendung von SQL Server-Kollatierungen (dh solche mit Namen, die mit beginnen SQL_) korrekt, wenn sie für VARCHARDaten verwendet werden. Dies gilt nicht genau für NVARCHARDaten oder VARCHARDaten, wenn eine Windows-Kollatierung verwendet wird (Namen, die nicht mit beginnen SQL_).
Solomon Rutzky