N'Șc 'считал дубликат ключа N'C', используя сопоставление Latin1_General_CI_AS


11

У меня есть таблица с уникальным ключом, который включает NVARCHAR(50)столбец (правильно или нет, но есть). Таким образом, при попытке вставить Șcили C(не имеет значения порядок вставки) он прерывается на 2-й вставке из-за проблем с сопоставлением. Вот ошибка:

(Затронуты 1 строка) Сообщение 2601, уровень 14, состояние 1, строка 16 Невозможно вставить строку дубликата ключа в объект "dbo.testT" с уникальным индексом "IX_TestT". Значение дубликата ключа (C).

Выберите возврат:

введите описание изображения здесь

База данных по умолчанию сортировки Latin1_General_CI_AS. Потратил некоторое время на поиски решения, не слишком меняя существующую структуру, но не мог найти способ начать работу. Перепробовал разные сопоставления и комбинации, все не получается. Читайте ( здесь и здесь ) о расширениях персонажей и так далее, все еще застрял. Вот пример кода, который я использую для репликации проблемы, не стесняйтесь изменять и рекомендовать все, что может помочь решить эту проблему.

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;

Ответы:


10

Проблема заключается в том, что старые сопоставления SQL Server (то есть с именами, начинающимися с SQL_) и первые две версии сопоставлений Windows ( 80серии, поставляемые с SQL Server 2000 и не имеющие номера версии в имени, и 90серии, которые пришел с SQL Server 2005) отсутствует вес сортировки для очень многих символов. В основном это было исправлено, начиная с 100серии Collation, которая шла с SQL Server 2008.

Как видно из приведенных ниже примеров, Șсимвол соответствует пустой строке при использовании недвоичного кода, параметров сравнения 80 или 90 (и параметров сортировки SQL Server), поскольку оба имеют одинаковый вес сортировки: 0. Ничего. Нада. Это означает, что при сравнении N'Șc'с N'C'(с использованием предварительной подборки 100) вы действительно сравниваете N'c'с N'C'(тест № 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)

Так что, к сожалению, вам нужно будет удалить PK, изменить столбец, чтобы иметь 100-уровневое сопоставление (например Latin1_General_100_CI_AS_SC), а затем воссоздать PK. Пожалуйста , обратите внимание , что разница в том , что предложила параметры сортировки из текущей сортировки как 100 и_SC в конце, что позволяет ему правильно обрабатывать дополнительные символы.

Это не значит, что вам нужно:

  1. изменить параметры сортировки других таблиц (если они не имеют такую ​​же настройку NVARCHARв ПК)
  2. изменить параметры сортировки базы данных по умолчанию. Основная проблема, которая заключается в том, чтобы не изменять параметры сортировки БД, заключается в разнице в поведении между операциями table.column = N'Ș'и тем, что @variable = N'Ș'переменные и строковые литералы используют параметры сортировки базы данных по умолчанию.

Дополнительные примеры такого поведения см. В разделе «Дополнительные символы» моего следующего блога:

Uni-Code: Поиск истинного списка допустимых символов для идентификаторов T-SQL, часть 3 из 2 (идентификаторы с разделителями)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.