In der Diskussion "Server Collation SQL_Latin1_General_CP1_CI_AS versus Latin1_General_CI_AS" in der MSDN-Gruppe "Getting started with SQL Server" wird ein sehr fortgeschrittenes Thema behandelt. Weil ich mich damit auch schon das eine oder andere Mal beschäftigen musste, möchte ich hier meine Erkenntnisse festhalten.

Unicode oder nicht?

Der wichtigste Unterschied besteht darin, dass die alten SQL-Collations, wie SQL_Latin1_General_CP1_CI_AS nur für Nicht-Unicode-Zeichenketten gelten. Sollte ich für ein NVARCHAR-Feld einer Tabelle diese Collation wählen, dann wird sie nicht verwendet. In Wirklichkeit wird dann automatisch Latin1_General_CI_AS verwendet.

Gemeinsamkeiten

Die Collation wirkt sich auf die Sortierungen, also auch auf Indexe, und die Gleichheit aus.

  • Generell haben beide Collations gemein, dass sie sich nur um die Sortierung der Zeichen aus der Codepage 1252, genauer "Latin1", kümmern. Bei Unicode werden darin nicht vorkommenden Zeichen komplett außerhalb sortiert.
  • Das "CI" steht für "case insensitiv", also große und kleine Buchstaben als gleich behandelt werden.
  • Käme noch ein "_Pref" im namen vor, dann gälte das auch aber bei ansonsten völlig gleichen Wörtern würden die Großbuchstaben zuerst kommen.
  • Das "AS" besagt, dass Akzente berücksichtigt werden, und Umlaute nicht wie die Basisbuchstaben behandelt werden, also "a"<>"ä". Die Umlaute folgen in der Sortierung aber unmittelbar nach den Vokalen.
  • Kürzere Zeichenketten stehen in der Sortierung vor ansonsten bis dahin gleichen. Angehängte Leerzeichen werden ignoriert.

Die Unterschiede liegen im Detail

Latin1_General_CI_AS ist eine Collation, die für Unicode und Nicht-Unicode verwendet werden kann. Sie ist ziemlich nahe an der DIN 5007-1, aber nicht ganz identisch. So gilt beispielsweise "ä" <> "ae", aber wegen des Zusatz "AS" auch "ä"<>"a".
Die Sortierung von zusammengesetzten Wörtern (wie "Glörfeld & Co KG") und Zahlen weicht leider etwas von der Norm ab, aber das wird selten bemerkt. Die Bindestrich-Wörter sind hingegen richtig ("aa" < "a-a" < "ab"). Als Besonderheit gegenüber der ansonsten ähnlichen SQL-Collation seit erwähnt, dass "ß" als Ligatur definiert ist und dementsprechend mit "ss" als gleichwertig behandelt wird. Hier gibt es zwischen Beiden also keine Präferenz. Die Reihenfolge bei ansonsten gleichwertigen Zeichenketten ist daher zufällig. SQL_Latin1_General_CP1_CI_AS gilt ausschließlich für Nicht-Unicode-Strings. Hier gilt zudem "ss" wird vor "ß", aber "ß" vor "st" sortiert. Bei gibt es ein schönes Collation Chart, dass die Sortierung der ersten Zeichen darstellt. Man muss aber bedenken, dass die Sortierung auch vom Folgebuchstaben abhängen kann.

Server-Collation, Datenbank-Collation oder pro Feld?

Selbst wenn man das weiß, dann kann es einem doch versehentlich passieren… Wenn man beim Anlegen einer Tabelle nicht bei jedem Zeichenkettenfeld (CHAR, NCHAR, VARCHAR und NVARCHAR) die Collation explizit angibt, dann wird die aktuelle Default-Collation der Datenbank verwendet. Wenn man beim Anlegen einer Datenbank keine Collation explizit angibt, dann wird die aktuelle Default-Collation des Servers verwendet.

Der folgende SQL-Befehl ermittelt die Default-Collation eines SQL Servers:
select SERVERPROPERTY ( 'Collation') as "Collation"

Und so wird die Default-Collation der aktuellen Datenbank ermittelt:
SELECT CAST(DATABASEPROPERTYEX(db_name(), 'Collation') AS sysname) AS "Collation"

Collation ändern?

Wenn man die Collation der Felder ändern will, dann reicht es dementsprechend nicht, einfach die Datenbank-Default-Collation zu ändern. Das hat nur Einfluss auf danach angelegte Felder, die ohne explizite Angabe erstellt werden…
Um die Collation von bestehenden Feldern zu ändern, muss man zunächst alle Indexe auf die Zeichenketten entfernen, das gilt freilich auch für Primärschlüssel, Unique-Constraints, etc. Dann muss man mittels ALTER TABLE pro Feld die Collation ändern. Dann kann man die Indexe wieder anlegen.

Es versteht sich von selber, dass das verlustfrei nur mit Unicode-Feldern klappt… 😉