N'Șc 'wurde als doppelter Schlüssel von N'C' unter Verwendung der Latin1_General_CI_AS-Kollatierung betrachtet


11

Ich habe eine Tabelle mit einem eindeutigen Schlüssel, der eine NVARCHAR(50)Spalte enthält (richtig oder nicht, aber vorhanden). Wenn Sie also versuchen, einzufügen Școder C(unabhängig von der Reihenfolge der Einfügung), wird die 2. Einfügung aufgrund von Sortierproblemen unterbrochen. Hier ist der Fehler:

(1 Zeile (n) betroffen) Meldung 2601, Ebene 14, Status 1, Zeile 16 Es kann keine doppelte Schlüsselzeile in das Objekt 'dbo.testT' mit dem eindeutigen Index 'IX_TestT' eingefügt werden. Der doppelte Schlüsselwert ist (C).

Rückgabe auswählen:

Geben Sie hier die Bildbeschreibung ein

Die Standardkollatierung der Datenbank lautet Latin1_General_CI_AS. Ich habe einige Zeit damit verbracht, nach Lösungen zu suchen, ohne die bereits vorhandene Struktur zu stark zu verändern, kann aber keinen Weg finden, um an die Arbeit zu gehen. Versucht verschiedene Kollatierungen und Kombinationen, alles schlägt fehl. Lesen Sie ( hier und hier ) über Charaktererweiterungen und so weiter. Hier ist ein Beispielcode, mit dem ich das Problem repliziere. Sie können ihn jederzeit ändern und empfehlen, um dieses Problem zu beheben.

CREATE TABLE testT (
    [Default_Collation]     [NVARCHAR] (50) COLLATE DATABASE_DEFAULT,
    [Latin1_General_CI_AS]  [NVARCHAR] (50) COLLATE Latin1_General_CI_AS,
    [Latin1_General_CI_AI]  [NVARCHAR] (50) COLLATE Latin1_General_CI_AI,
    [SQL_Collation]         [NVARCHAR] (50) COLLATE SQL_Latin1_General_CP1_CI_AS);
CREATE UNIQUE CLUSTERED INDEX [IX_TestT] ON [dbo].[testT] ([Default_Collation])
ON [PRIMARY]
GO

INSERT INTO testT
SELECT  N'Șc',  --COLLATE Latin1_General_CI_AS
        N'Șc',  --COLLATE Latin1_General_CI_AS
        N'Șc',  --COLLATE Latin1_General_CI_AS
        N'Șc'   --COLLATE Latin1_General_CI_AS

INSERT INTO testT
SELECT  N'C'    --COLLATE Latin1_General_CI_AS 
        ,N'C'   --COLLATE Latin1_General_CI_AS
        ,N'C'   --COLLATE Latin1_General_CI_AS
        ,N'C'   --COLLATE SQL_Latin1_General_CP1_CI_AS

SELECT * FROM testT;

DROP TABLE testT;

Antworten:


10

Das Problem ist, dass die alten SQL Server-Kollatierungen (dh diejenigen mit Namen, die mit beginnen SQL_) und die ersten beiden Versionen der Windows-Kollatierungen (die 80Serie, die mit SQL Server 2000 geliefert wurde und keine Versionsnummer im Namen hat, und die 90Serie, die kam mit SQL Server 2005) fehlen die Sortiergewichte für sehr viele Zeichen. Dies wurde größtenteils korrigiert, beginnend mit der 100Serie Collations, die mit SQL Server 2008 geliefert wurde.

Wie Sie in den folgenden Beispielen sehen können, Șstimmt das Zeichen mit einer leeren Zeichenfolge überein, wenn nicht-binäre Kollatierungen der Version 80 oder 90 (und SQL Server-Kollatierungen) verwendet werden, da beide das gleiche Sortiergewicht haben: 0. Nichts. Nada. Dies bedeutet, dass Sie beim Vergleich N'Șc'mit N'C'(unter Verwendung von 100 Kollatierungen vor der Serie) wirklich N'c'mit N'C'(Test Nr. 1) vergleichen:

SELECT 1 WHERE N'Șc' = N'C' COLLATE Latin1_General_CS_AS;
-- no result (due to "c" and "C" being different case)

SELECT 2 WHERE N'Ș' = N'' COLLATE SQL_Latin1_General_CP1_CI_AS;
SELECT 3 WHERE N'Ș' = N'' COLLATE Latin1_General_CI_AS;

SELECT 4 WHERE N'Ș' = N'' COLLATE Latin1_General_BIN2;
-- no result (due to "Ș" still being a code point and empty string has no code points)

SELECT 5 WHERE N'Ș' = N'' COLLATE Latin1_General_100_CI_AS;
-- no result (due to "Ș" finally having a sort weight in 100 series Collations)

SELECT 6 WHERE N'Ș' = N'' COLLATE Chinese_PRC_CI_AI;
SELECT 7 WHERE N'Ș' = N'' COLLATE Chinese_PRC_90_CI_AI;

SELECT 8 WHERE N'Ș' = N'' COLLATE Indic_General_90_CI_AI;
SELECT 9 WHERE N'Ș' = N'' COLLATE Indic_General_100_CI_AI;
-- no result (due to "Ș" finally having a sort weight in 100 series Collations)

Leider müssen Sie die PK löschen, die Spalte ändern, um eine Kollatierung mit 100 Ebenen zu erhalten (z. B. Latin1_General_100_CI_AS_SC), und dann die PK neu erstellen. Bitte beachten Sie, dass der Unterschied zwischen der vorgeschlagenen Kollatierung und der aktuellen Kollatierung sowohl der 100 als auch der _SCam Ende ist, wodurch zusätzliche Zeichen ordnungsgemäß verarbeitet werden können.

Dies bedeutet nicht , dass Sie:

  1. Ändern Sie die Sortierungen anderer Tabellen (es sei denn, sie haben das gleiche Setup wie NVARCHARin der PK).
  2. Ändern Sie die Standardkollatierung der Datenbank. Das Hauptproblem, wenn die Sortierung der Datenbank nicht geändert wird, besteht darin, dass es einen Verhaltensunterschied zwischen der Ausführung table.column = N'Ș'und der @variable = N'Ș'Verwendung der Standardkollatierung der Datenbank durch Variablen und Zeichenfolgenliterale gibt.

Weitere Beispiele für dieses Verhalten finden Sie im Abschnitt "Ergänzende Zeichen" des folgenden Blogposts von mir:

Der Uni-Code: Die Suche nach der wahren Liste gültiger Zeichen für T-SQL-Bezeichner, Teil 3 von 2 (Begrenzte Bezeichner)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.