N'Șc 'rozpatrywał zduplikowany klucz N'C' używając sortowania Latin1_General_CI_AS


11

Mam tabelę z unikalnym kluczem zawierającym NVARCHAR(50)kolumnę (poprawną lub nie, ale tam jest). Tak więc podczas próby wstawienia Șclub C(bez względu na kolejność wstawiania) łamie się na 2. wkładce z powodu problemów z sortowaniem. Oto błąd:

(Dotyczy 1 wierszy) Msg 2601, poziom 14, stan 1, wiersz 16 Nie można wstawić zduplikowanego wiersza klucza w obiekcie „dbo.testT” z unikalnym indeksem „IX_TestT”. Zduplikowana wartość klucza to (C).

Wybierz zwroty:

wprowadź opis zdjęcia tutaj

Domyślne sortowanie bazy danych to Latin1_General_CI_AS. Spędziłem trochę czasu, zastanawiając się, jak go rozwiązać, nie zmieniając zbytnio już istniejącej struktury, ale nie mogę znaleźć sposobu na rozpoczęcie pracy. Próbowałem różnych zestawień i kombinacji, wszystko się nie udaje. Przeczytaj ( tutaj i tutaj ) o rozszerzeniach postaci i tak dalej, nadal utknął. Oto przykładowy kod, którego używam do replikacji problemu, możesz go zmodyfikować i polecić wszystko, co mogłoby pomóc w rozwiązaniu tego problemu.

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;

Odpowiedzi:


10

Problem polega na tym, że stare SQL Server Collations (tj. O nazwach rozpoczynających się od SQL_) i dwie pierwsze wersje Windows Collations ( 80seria, która pochodzi z SQL Server 2000 i nie ma numeru wersji w nazwie, oraz 90seria, która przyszedł z SQL Server 2005) brakuje wagi sortowania dla wielu znaków. Zostało to głównie poprawione, zaczynając od 100serii Sortowania dostarczonej z SQL Server 2008.

Jak widać w poniższych przykładach, Șznak pasuje do pustego ciągu, gdy używa się niebinarnych zestawień 80 lub 90 zestawień (i zestawień SQL Server), ponieważ oba mają taką samą wagę sortowania: 0. Nic. Nada. Oznacza to, że przy porównywaniu N'Șc'z N'C'(za pomocą wstępnego sortowania serii 100), jesteś naprawdę porównujące N'c'z N'C'(test # 1):

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)

Tak więc, niestety, będziesz musiał upuścić PK, zmienić kolumnę, aby uzyskać 100-poziomowe sortowanie (np. Latin1_General_100_CI_AS_SC), A następnie ponownie utworzyć PK. Należy pamiętać, że różnica w sugerowanej Sortowanie od bieżącego Układanie jest zarówno 100 i_SC na koniec, co pozwala mu prawidłowo obsługiwać znaki uzupełniające.

Ten sposób nie oznacza, że trzeba:

  1. zmień układanie innych tabel (chyba że mają takie same ustawienia NVARCHARw PK)
  2. zmień domyślne sortowanie bazy danych. Głównym problemem z nie zmieniając DB Sortowanie jest to, że nie będzie różnicy między zachowaniem robi table.column = N'Ș'i @variable = N'Ș'ponieważ zmienne i literały łańcuchowe użyć domyślnej bazy danych za zestawień.

Aby uzyskać więcej przykładów tego zachowania, zobacz sekcję „Postacie uzupełniające” poniższego mojego posta na blogu:

Uni-Code: Poszukiwanie prawdziwej listy prawidłowych znaków dla identyfikatorów T-SQL, część 3 z 2 (Identyfikatory rozdzielane)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.