为什么两个不同值的插入会导致唯一约束冲突?

时间:2019-10-18 13:57:15

标签: sql-server

给出下表定义

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对象。重复的键值为(桑日县ཟངས་རི་རྫོང་།,Sangri)。

1 个答案:

答案 0 :(得分:4)

正如我在评论中提到的,这很可能是由于您使用的归类。无论您使用哪种默认排序规则,为了比较目的,都会忽略字符'ཟངས་རི་རྫོང་།'。例如,将归类强制为Latin1_General_CI_AS replicates,该错误是

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'桑日县 ཟངས་རི་རྫོང་།' );
  

消息2627的14级状态1线路2
  违反UNIQUE KEY约束“ UI_Test_NamePair”。无法在对象“ dbo.Test”中插入重复密钥。重复的键值为(桑日县ཟངས་རི་རྫོང་།,Sangri)。
  讯息3621等级0状态0线路2
  该声明已终止。

解决问题的一种方法是使用不同的排序规则,例如binary collation

--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'桑日县 ཟངས་རི་རྫོང་།' );

请注意,结果是,在使用默认排序规则将其他列的值进行比较时,可能会出现排序错误。因此,您可能要使用computed column,并强制使用以下排序规则和索引:

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'桑日县 ཟངས་རི་རྫོང་།' );