Bei der Installation einer SQL Server Instanz schlägt der Installationassistent die Sortierung Latin1_General_CI_AS vor. Hat man keine anderen Vorgaben, so übernimmt man diese Einstellung und der SQL Server wird mit dieser Sortierung installiert. Soweit so gut. In den meisten Fällen wir es zu keinen Problemen mit der Sortierung kommen. Es sei den man möchte einen eindeutigen Index für eine Spalte mit einem Zeichendatentyp erstellen. Der SQL Server interpretiert nämlich 'ß' gleich 'ss'. Da kann zum Problem werden, wenn man in die entsprechende Spalten die Werte 'Claußen' und 'Claussen' einfügen will. Beide Werte sind zwei verschieden Nachnamen und somit eindeutig. Abhilfe schafft da, die Änderung der Sortierung für die entsprechende Spalte.
-- ß=ss
-- Datenbank mit Standardsortierung erstellen
-- Latin1_General_CI_AS war jene sortierung die bei der Installation der Instanz agegeben wurde
USE [master]
GO
CREATE DATABASE [demo]
GO
ALTER DATABASE [demo] COLLATE Latin1_General_CI_AS
GO
-- Tabelle test erstellen
USE [demo]
GO
CREATE TABLE [test] ([Nachname] char(20) NOT NULL, [stadt] char(20) NULL)
GO
-- Tabelle mit Testdatensätzen füllen
INSERT [test] VALUES (N'Claussen', N'BGH')
INSERT [test] VALUES (N'Claußen', N'MUC')
GO
-- 1. Versuch einen UNIQUE-Index zu erstellen
CREATE UNIQUE CLUSTERED INDEX [ix_name] ON [dbo].[test] ([Nachname] ASC)
GO
-- Ergebnis
/*
Meldung 1505, Ebene 16, Status 1, Zeile 2
Die CREATE UNIQUE INDEX-Anweisung wurde beendet, weil ein doppelter Schlüssel für den Objektnamen 'dbo.test' und den Indexnamen 'ix_name' gefunden wurde. Der doppelte Schlüsselwert ist (Claußen ).
Die Anweisung wurde beendet.
*/
-- Warum?
/*
Laut DIN, SQL ANSI-92 und ISO Normen wird 'ß' wie 'ss' behandelt.
*/
-- Überprüfung!
SELECT CASE WHEN 'ss' = 'ß' THEN 'ss = ß!' ELSE 'ok' END AS 'Test ss=ß',
CASE WHEN 'ss' = 's' THEN 'ss = s!' ELSE 'ok' END AS 'Test ss=s',
CASE WHEN 'ae' = 'ä' THEN 'ae = ä!' ELSE 'ok' END AS 'Test ae=ä',
CASE WHEN 'oe' = 'ö' THEN 'oe = ö!' ELSE 'ok' END AS 'Test oe=ö',
CASE WHEN 'ue' = 'ü' THEN 'ue = ü!' ELSE 'ok' END AS 'Test ue=ü'
-- Ergebnis
/*
Test ss=ß Test ss=s Test ae=ä Test oe=ö Test ue=ü
--------- --------- --------- --------- ---------
ss = ß! ok ok ok ok
*/
-- Sortierung ändern
USE [master]
GO
ALTER DATABASE [demo] COLLATE SQL_Latin1_General_CP1_CI_AS
GO
-- Wieder überprüfen
USE [demo]
GO
SELECT CASE WHEN 'ss' = 'ß' THEN 'ss = ß!' ELSE 'ok' END AS 'Test ss=ß',
CASE WHEN 'ss' = 's' THEN 'ss = s!' ELSE 'ok' END AS 'Test ss=s',
CASE WHEN 'ae' = 'ä' THEN 'ae = ä!' ELSE 'ok' END AS 'Test ae=ä',
CASE WHEN 'oe' = 'ö' THEN 'oe = ö!' ELSE 'ok' END AS 'Test oe=ö',
CASE WHEN 'ue' = 'ü' THEN 'ue = ü!' ELSE 'ok' END AS 'Test ue=ü'
-- Ergebnis
/*
Test ss=ß Test ss=s Test ae=ä Test oe=ö Test ue=ü
--------- --------- --------- --------- ---------
ok ok ok ok ok
Die Sortierung SQL_Latin1_General_CP1_CI_AS würde dieses Problem beheben.
*/
-- 2. Versuch einen UNIQUE-Index zu erstellen
CREATE UNIQUE CLUSTERED INDEX [ix_name] ON [dbo].[test] ([Nachname] ASC)
GO
-- Ergebnis
/*
Meldung 1505, Ebene 16, Status 1, Zeile 2
Die CREATE UNIQUE INDEX-Anweisung wurde beendet, weil ein doppelter Schlüssel für den Objektnamen 'dbo.test' und den Indexnamen 'ix_name' gefunden wurde. Der doppelte Schlüsselwert ist (Claußen ).
Die Anweisung wurde beendet.
*/
-- Was nun?
-- Sortierung der Spalte 'Nachname' überprüfen
SELECT [name], [collation_name] FROM sys.columns
WHERE [name] = N'Nachname'
-- Ergebnis
/*
name collation_name
-------- --------------------
Nachname Latin1_General_CI_AS
Jetzt ist alles klar! Die bestehende Sortierung der Spalte 'Nachname' wurde nicht geändert.
*/
-- Sortierung der Spalte 'Nachname' ändern
ALTER TABLE [test]
ALTER COLUMN [Nachname] char(20)
COLLATE SQL_Latin1_General_CP1_CI_AS
GO
-- Sortierung der Spalte 'Nachname' wieder überprüfen
SELECT [name], [collation_name] FROM sys.columns
WHERE [name] = N'Nachname'
-- Ergebnis
/*
name collation_name
-------- ----------------------------
Nachname SQL_Latin1_General_CP1_CI_AS
*/
-- 3. Versuch einen UNIQUE-Index zu erstellen
CREATE UNIQUE CLUSTERED INDEX [ix_name] ON [dbo].[test] ([Nachname] ASC)
GO
-- Ergebnis
/*
Befehl(e) wurde(n) erfolgreich abgeschlossen.
*/