SQL Server ignore_dup_key显然忽略了merge语句

nim*_*dil 3 merge unique-key sql-server-2008

SQL Server 2008.

我有几段代码一起工作,效果很奇怪所以我决定分享.

我有一个包含电子邮件的表 - 为简单起见,假设有2列:ID identity(1,1)int primary key email varchar(900)

此外,电子邮件列上还有一个唯一键,IGNORE_DUP_KEY = ON.

问题的另一方面是合并声明:

merge into dbo.email
using (
     select distinct email t from #t
) p 
ON t = email
when not matched by target then
insert (email) values  (t);
Run Code Online (Sandbox Code Playgroud)

值得注意的是,#t基本上是(为了这个查询的目的)一个带有电子邮件varchar(500)的列表.

令人惊讶的是查询失败:

"违反UNIQUE KEY约束'uq_email'.无法在对象dbo.email中插入重复键"

然而,这完美无缺:

insert into dbo.email (email) select email from #t
Run Code Online (Sandbox Code Playgroud)

虽然我显然可以解决这个问题(无论如何插入语句更快,所以它是一种方法)我不知道为什么MERGE语句失败.任何想法,任何人?

编辑:完整用例:第1步:

create table #temp (
col1 varchar(500),
col2 varchar(500),
col3 varchar(500),
col4 varchar(500),
col5 varchar(500),
email varchar(500),
id int)
Run Code Online (Sandbox Code Playgroud)

第2步:

出于多种目的,从CSV文件中填充#temp

第3步:

使用(从#temp中选择不同的电子邮件t)合并到dbo.email中p ON t =当与目标不匹配时的电子邮件然后插入(电子邮件)值(t);

第0步 - 为dbo.email创建脚本:

CREATE TABLE dbo.email (
id int identity(1,1) not null,
email varchar(900) null,
loaddate date default null,
constraint [PK__email__1111] PRIMARY KEY CLUSTERED
(
    id asc
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY,
CONSTRAINT [uq_email] UNIQUE NONCLUSTERED
(
     EMAIL asc
)
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = ON, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY
) ON PRIMARY
Run Code Online (Sandbox Code Playgroud)

如果不给你数十亿字节的数据显然是一个问题,我就无法做得更多.

Mik*_*son 7

您的电子邮件列允许使用null值.如果您null在目标中有null值,而在源中有值,则它们将不会在on表达式中匹配.插入第二个null值时,您将遇到唯一的约束异常.

试试这个:

merge into dbo.email
using (
     select distinct email t from #t where email is not null
) p 
ON t = email
when not matched by target then
insert (email) values  (t);
Run Code Online (Sandbox Code Playgroud)

更新:
关于ignore_dup_key您应该阅读合并声明的文档中的备注部分:

如果对目标表上的任何唯一索引将IGNORE_DUP_KEY设置为ON,则MERGE将忽略此设置.

要在SQL Server中具有允许多个空值的唯一约束,您应该添加唯一的筛选索引.

create unique index UX_xx on TableName(ColName) where ColName is not null
Run Code Online (Sandbox Code Playgroud)

  • 精彩的捕获.此外,我可能永远不会习惯在SQL Server中的事实 - 与ORacle不同 - 唯一列只允许一个空值. - >但是 - 虽然它确实解释了为什么合并没有捕获null = null的情况,但它没有解释为什么ignore_dup_key在这种情况下不起作用.毕竟它适用于insert语句. (2认同)