Haben Sie sich schon einmal gefragt, ob Ihre Daten Ihnen tatsächlich die Wahrheit sagen? Ich hasste es, als ich entdeckte, dass eine simple Einstellung in SQL Server – die Kollation – meine mühsam berechneten Prüfsummen ins Wanken brachte. Plötzlich standen identische Datensätze im Verdacht, manipuliert oder fehlerhaft zu sein, nur weil eine Datenbank die Zeichen anders sortierte! In meinem Fall prallten die Kollationen SQL_Latin1_General_CP1_CI_AI und Latin1_General_100_CI_AI frontal aufeinander – und ich saß in der Falle, ohne zu wissen, wem ich noch vertrauen konnte. Begleiten Sie mich auf der spannenden Jagd nach der einen Ursache, die mein Daten-Domino zum Einsturz gebracht hat, und erfahren Sie, wie Sie selbst zum Chef Ihrer Prüfsummen werden!

Einleitung

Die SQL-Server-Funktion CHECKSUM berechnet einen 32-Bit-Hash auf Basis von Sortiergewichten, die durch die jeweilige Kollation definiert sind. Daher liefert derselbe Text je nach Kollation unterschiedliche Prüfsummenwerte. Die Kollationen SQL_Latin1_General_CP1_CI_AI (eine SQL-Kollation) und Latin1_General_100_CI_AI (eine Windows-Kollation, Version 100) unterscheiden sich in ihren Sortier- und Vergleichsregeln – insbesondere in der Behandlung von Unicode-Erweiterungen, Zeichenexpansionen und Code-Page-Zuweisungen. Als Folge kann CHECKSUM auf einer Datenbank mit SQL_Latin1_General_CP1_CI_AI einen anderen Integer zurückliefern als auf einer Datenbank mit Latin1_General_100_CI_AI, selbst wenn die zugrundeliegenden Zeichenketten identisch sind. Zu Workarounds zählen die Funktionen BINARY_CHECKSUM (kolationsunabhängig), HASHBYTES (kryptografisch sicherer) sowie das explizite Anwenden einer binären Kollation oder die Verwendung von UTF-8/Unicode-Datentypen.

Grundlagen: Was ist eine Kollation?

Kollationen definieren, wie Zeichen in Datenbanken intern codiert, sortiert und verglichen werden [Microsoft Learn]. Sie umfassen Regeln für Groß-/Kleinschreibung, Akzentsensitivität und Unicode-Äquivalenzen [Stack Overflow].

Bitmuster und Sortierregeln

Eine Kollation legt die Bitmuster und Sortierregeln fest, die SQL Server bei Vergleichen und Sortierungen von Textdaten verwendet [Microsoft Learn]. Differierende Sortiergewichte können bereits dazu führen, dass zwei scheinbar gleiche Zeichenketten in verschiedenen Kollationen als unterschiedlich behandelt werden [SQLTeam.com Forums | Stack Overflow].

„A collation specifies the bit patterns that represent each character in a dataset. Collations also determine the rules that sort and compare data.“

Microsoft Learn

SQL- vs. Windows-Kollationen

QL-Kollationen wie SQL_Latin1_General_CP1_CI_AI basieren auf legacy Code Pages und verwenden teilweise abweichende Regeln im Vergleich zu Windows-Kollationen [Stack Overflow].
Windows-Kollationen wie Latin1_General_100_CI_AI sind Unicode-fokussiert, verwenden Code Page 1252 einheitlich für Unicode- und Nicht-Unicode-Daten und unterscheiden sich in Zeichenexpansionen wie „ß“ ↔ „ss“ oder „æ“ ↔ „ae“ [Microsoft Learn].
Diese Unterschiede können bereits bei einfachen Vergleichs- oder Sortiervorgängen zu abweichenden Ergebnissen führen [Sql Chit Chat].

  • SQL_Latin1_General_CP1_CI_AI ist eine SQL-Kollation, bei der nicht-Unicode- und Unicode-Vergleiche nach unterschiedlichen Regeln erfolgen.
  • Latin1_General_100_CI_AI ist eine Windows-Kollation (Version 100), bei der Unicode- und Nicht-Unicode-Daten gleich behandelt werden und Code-Page 1252 zugrunde liegt. [SQLServerCentral | Microsoft Learn]

Unterschiede zeigen sich unter anderem bei Zeichenexpansionen („ß“ ↔ “ss”, „æ“ ↔ “ae” usw.), was direkte Auswirkungen auf Vergleichsoperationen hat. [SQLServerCentral]

Funktionsweise von CHECKSUM

Die T-SQL-Funktion CHECKSUM berechnet einen 32-Bit-Hash über eine Liste von Ausdrücken und eignet sich primär zum Aufbau von Hash-Indizes [Dokumentation & Hilfe]. Dabei spielt die Reihenfolge der Argumente ebenso eine Rolle wie die zugrundeliegende Kollation, da CHECKSUM die Kollations-Regeln beim Hashing berücksichtigt [Microsoft Learn].

Microsoft dokumentiert explizit, dass der Rückgabewert von CHECKSUM von der Kollation abhängt und bei unterschiedlichen Kollationen abweichen kann [Microsoft Learn]. Ein identischer Textwert liefert daher unter SQL_Latin1_General_CP1_CI_AI einen anderen CHECKSUM-Wert als unter Latin1_General_100_CI_AI [Stack Overflow].

„The CHECKSUM value depends on the collation. The same value stored with a different collation will return a different CHECKSUM value.“

Microsoft Learn

Probleme und Kollisionsrisiken

Da CHECKSUM ein einfacher, nicht-kryptografischer Hash ist, können Kollisionen auftreten, bei denen unterschiedliche Eingabewerte denselben Hash erzeugen [Stack Overflow]. Zusätzlich entfernt CHECKSUM bei nchar– und nvarchar-Strings führende und nachgestellte Leerzeichen, was zu weiteren unerwarteten Ergebnissen führen kann [Microsoft Learn].

Warum entstehen unterschiedliche Prüfsummen?

Unterschiedliche Sortiergewichte in SQL- und Windows-Kollationen sorgen für abweichende interne Bitrepräsentationen der gleichen Zeichenketten [SQLTeam.com Forums]. Unicode-Erweiterungen und Zeichenexpansionen werden in Windows-Kollationen anders behandelt als in SQL-Kollationen, was das Ergebnis von CHECKSUM direkt beeinflusst [SQLTeam.com Forums]. Auch die Art und Weise, wie CHECKSUM führende und nachgestellte Leerzeichen sowie Bindestriche berücksichtigt, variiert je nach Kollation und Datentyp [Microsoft Learn].

  1. Kollationsabhängige Sortiergewichte
    CHECKSUM nutzt intern die Gewichte, die eine Kollation Zeichen zuweist. Unterschiedliche Kollationen führen so zu unterschiedlichen Integer-Resultaten.
  2. Computed Columns mit Kollationsunterschieden
    Wendet man CHECKSUM auf eine berechnete Spalte an, deren Kollation abweicht, ändert sich das Ergebnis: „…the collation affected the computed column collation, the collation affected the checksum.“ [SQLServerCentral]
  3. Unterschiede zwischen SQL- und Windows-Kollationen
    SQL-Kollationen wie SQL_Latin1_General_CP1_CI_AI folgen anderen Nicht-Unicode-Regeln als Windows-Kollationen wie Latin1_General_100_CI_AI, was bereits beim Vergleich gleicher Zeichenketten zu unterschiedlichen Ergebnissen führt. [SQLServerCentral]
  4. Unicode-Sensitivität
    Der Wechsel zu einer Unicode-sensitiven Kollation (z. B. Latin1_General_CI_AI) ändert die Prüfsummen durch andere Zeichenrepräsentationen: „If you change it to a Unicode sensitive collation like Latin1_General_CI_AI it returns different checksum for your values… Using NVARCHAR also returns different checksum, which confirms that this is an Unicode matter.“ [Stack Overflow]
  5. Kollisionsverhalten bei bestimmten Zeichen
    Einfache Hash-Algorithmen wie CHECKSUM können bei Zeichen wie Bindestrichen („-“) collidieren, da sie kollationsabhängigen Regeln folgen: „This has to do with how CHECKSUM calculates over (N)CHAR values with particular collations; … as if the string had all hyphens stripped.“ [Stack Overflow]

Workarounds und Alternativen

  • BINARY_CHECKSUM
    Führt eine binäre Auswertung durch und ist kollationsunabhängig: „BINARY_CHECKSUM computes the checksum based on this binary representation of the data … BINARY_CHECKSUM is collation insensitive.“ [SQLServerCentral]
  • HASHBYTES
    Verwendet kryptografische Hash-Algorithmen (MD5, SHA2, …) und ist ebenfalls kollationsunabhängig – jedoch speicherintensiver: „HASHBYTES … is immune from the problems faced by CHECKSUM and BINARY_CHECKSUM … it is case-sensitive, collation insensitive …“ [SQLServerCentral]
  • Explizite Binärkollation
    Durch Anfügen von COLLATE Latin1_General_BIN2 an den String kann man konsistente, kollationsunabhängige Werte erzwingen: „…you can … explicitly add COLLATE Latin1_General_BIN2 to the strings…“ [Stack Overflow]
  • Einheitliche Kollation im Abfragekontext
    Vor der CHECKSUM-Berechnung alle beteiligten Spalten mit COLLATE auf eine einheitliche Kollation bringen (z. B. Latin1_General_100_CI_AI).
  • Verwendung von Unicode-Datentypen
    NVARCHAR in Kombination mit einer Unicode-Windows-Kollation kann einige SQL-Kollations-Eigenheiten umgehen. [Stack Overflow]

Fazit

Die Wahl der richtigen Kollation ist kein Nebenschauplatz, sondern essenziell für konsistente Prüfsummen mit CHECKSUM. Mit BINARY_CHECKSUM, HASHBYTES oder einer expliziten Binärkollation stehen Ihnen zuverlässige Alternativen zur Verfügung. Seien Sie sich stets bewusst, welche Sortier- und Vergleichsregeln Ihre Datenbank anwendet, um Überraschungen beim Hashing zu vermeiden [Reitse’s blog].

Weiterführende Links