Почему эта вставка двух разных значений вызывает нарушение уникального ограничения? - PullRequest
4 голосов
/ 18 октября 2019

Учитывая следующее определение таблицы

CREATE TABLE Test
(
  ID bigint IDENTITY( 1, 1 ) not null,
  NativeName nvarchar(150) not null,
  EnglishName nvarchar(150) null,
  CONSTRAINT PK_Test PRIMARY KEY NONCLUSTERED ( ID )
);

ALTER TABLE Test ADD CONSTRAINT UI_Test_NamePair UNIQUE (NativeName, EnglishName);

Почему следующие операторы вызывают нарушение уникального ограничения на второй вставке? И есть ли способ обойти это?

INSERT INTO Test( EnglishName, NativeName ) VALUES ( N'Sangri', N'桑日县' );
INSERT INTO Test( EnglishName, NativeName ) VALUES ( N'Sangri', N'桑日县 ཟངས་རི་རྫོང་།' );

Это приводит (переведено):

Нарушение ограничения UNIQUE KEY "UI_Test_NamePair". Дубликат ключа не может быть вставлен в объект Test. Значение ключа-дубликата равно (ang 日 县 ཟངས་ རི་ རྫོང་ །, Сангри).

1 Ответ

4 голосов
/ 18 октября 2019

Как я уже упоминал в комментарии, это, вероятно, связано с тем, что вы используете сопоставление. Независимо от того, что вы используете по умолчанию, символы 'ཟངས་རི་རྫོང་།' игнорируются для сравнения. Например, принудительное сопоставление для Latin1_General_CI_AS повторяет эту ошибку:

CREATE TABLE Test
(
  ID bigint IDENTITY( 1, 1 ) not null,
  NativeName nvarchar(150) COLLATE LATIN1_GENERAL_CI_AS NOT NULL,
  EnglishName nvarchar(150) null,
  CONSTRAINT PK_Test PRIMARY KEY NONCLUSTERED ( ID )
);

ALTER TABLE Test ADD CONSTRAINT UI_Test_NamePair UNIQUE (NativeName, EnglishName);

INSERT INTO Test( EnglishName, NativeName ) VALUES ( N'Sangri', N'桑日县' );
INSERT INTO Test( EnglishName, NativeName ) VALUES ( N'Sangri', N'桑日县 ཟངས་རི་རྫོང་།' );

Msg 2627 Уровень 14 Состояние 1 Строка 2Нарушение ограничения UNIQUE KEY 'UI_Test_NamePair'. Невозможно вставить дубликат ключа в объект 'dbo.Test'. Дубликат значения ключа ((日 县 ཟངས་ རི་ རྫོང་ །, Сангри). Msg 3621 Уровень 0 Состояние 0 Линия 2Оператор был прерван.

Один из способов решения этой проблемы - использовать другое сопоставление, например двоичное сопоставление :

--Ensure you drop prior test table
CREATE TABLE Test
(
  ID bigint IDENTITY( 1, 1 ) not null,
  NativeName nvarchar(150) COLLATE Latin1_General_BIN NOT NULL,
  EnglishName nvarchar(150) null,
  CONSTRAINT PK_Test PRIMARY KEY NONCLUSTERED ( ID )
);

ALTER TABLE Test ADD CONSTRAINT UI_Test_NamePair UNIQUE (NativeName, EnglishName);

INSERT INTO Test( EnglishName, NativeName ) VALUES ( N'Sangri', N'桑日县' );
INSERT INTO Test( EnglishName, NativeName ) VALUES ( N'Sangri', N'桑日县 ཟངས་རི་རྫོང་།' );

Примечаниечто в результате при сравнении значений со столбцами других пользователей с вашим сопоставлением по умолчанию вы, скорее всего, получите ошибки сопоставления. Таким образом, вы могли бы захотеть использовать вычисляемый столбец и установить параметры сортировки и индекса:

CREATE TABLE Test
(
  ID bigint IDENTITY( 1, 1 ) not null,
  NativeName nvarchar(150) NOT NULL,
  NativeNameBinCollated AS NativeName COLLATE Latin1_General_BIN PERSISTED,
  EnglishName nvarchar(150) null,
  CONSTRAINT PK_Test PRIMARY KEY NONCLUSTERED ( ID )
);

ALTER TABLE Test ADD CONSTRAINT UI_Test_NamePair UNIQUE (NativeNameBinCollated, EnglishName);

INSERT INTO Test( EnglishName, NativeName ) VALUES ( N'Sangri', N'桑日县' );
INSERT INTO Test( EnglishName, NativeName ) VALUES ( N'Sangri', N'桑日县 ཟངས་རི་རྫོང་།' );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...