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
Microsoft LearnCHECKSUM
value depends on the collation. The same value stored with a different collation will return a differentCHECKSUM
value.“
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].
- Kollationsabhängige Sortiergewichte
CHECKSUM
nutzt intern die Gewichte, die eine Kollation Zeichen zuweist. Unterschiedliche Kollationen führen so zu unterschiedlichen Integer-Resultaten. - Computed Columns mit Kollationsunterschieden
Wendet manCHECKSUM
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] - Unterschiede zwischen SQL- und Windows-Kollationen
SQL-Kollationen wieSQL_Latin1_General_CP1_CI_AI
folgen anderen Nicht-Unicode-Regeln als Windows-Kollationen wieLatin1_General_100_CI_AI
, was bereits beim Vergleich gleicher Zeichenketten zu unterschiedlichen Ergebnissen führt. [SQLServerCentral] - 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 likeLatin1_General_CI_AI
it returns different checksum for your values… UsingNVARCHAR
also returns different checksum, which confirms that this is an Unicode matter.“ [Stack Overflow] - Kollisionsverhalten bei bestimmten Zeichen
Einfache Hash-Algorithmen wieCHECKSUM
können bei Zeichen wie Bindestrichen („-“) collidieren, da sie kollationsabhängigen Regeln folgen: „This has to do with howCHECKSUM
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 byCHECKSUM
andBINARY_CHECKSUM
… it is case-sensitive, collation insensitive …“ [SQLServerCentral] - Explizite Binärkollation
Durch Anfügen vonCOLLATE Latin1_General_BIN2
an den String kann man konsistente, kollationsunabhängige Werte erzwingen: „…you can … explicitly addCOLLATE Latin1_General_BIN2
to the strings…“ [Stack Overflow] - Einheitliche Kollation im Abfragekontext
Vor derCHECKSUM
-Berechnung alle beteiligten Spalten mitCOLLATE
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
- CHECKSUM (Transact-SQL) – Microsoft Docs
- Collation and Unicode Support – Microsoft Docs
- An in-depth look at change detection in SQL Server – Part 02 – SQLServerCentral
- Difference between collation SQL_Latin1_General_CP1_CI_AS and Latin1_General_CI_AS – SQLServerCentral Blog
- Windows Collation Name: Latin1_General_100_CI_AS – Microsoft Docs
- Checksum with different string returns the same output – StackOverflow (Jeroen Mostert)
- SQL Collation – SQL_Latin1_General_CP1_CI_AS vs. Latin1_General_CI_AS – Community Dynamics Blog
- Why CHECKSUM returns the same value for different string? – StackOverflow (Major)
- Checksum function is dependent on Unicode? – StackOverflow (Martin Smith)
- CHECKSUM vs BINARY_CHECKSUM vs HASHBYTES – Push-Force.dev
- Mind your collation! – SQLReitse Blog