我在SQL Server 2008企业上运行查询时遇到问题。 查询是从另一个表插入到表,但它检查记录是否只插入一次。 查询执行如下操作:
insert into A(...)
--complex select from table B as b
WHERE NOT EXISTS (SELECT 1 FROM A WHERE id = b.id)
编辑:此查询执行以下操作: 如果来自B的“复数选择”选择记录45(即id = 45的记录)两次,则第一次记录45的where为真,则将其插入A. 然后出现第二个时间记录45,其中where条件为false,因此它不会在A中插入两次。
这个查询在SQL Server 2008标准版上运行正常,所以我认为问题是SQL Server版本之间的区别(比如默认设置不同或者什么) 我正在阅读最大插入提交大小,但我不确定这是否可能是问题。 没有错误消息,唯一可见的错误是在标准我得到记录45一次,在企业我得到它两次。 任何想法?
答案 0 :(得分:1)
我很确定你说你使用标准版的行为是出于其他原因,而不是你认为的那样。
您似乎期望如果您的INSERT
ed值包含重复项,那么INSERTED
将会NOT EXISTS
,因为新的存在,INSERT .. SELECT
将评估为false添加了行。然而AFAIK并不是它应该工作的方式。查看下面的简单CREATE TABLE A(id INT PRIMARY KEY)
CREATE TABLE B(id INT PRIMARY KEY)
INSERT INTO A
SELECT *
FROM B
。
NOT EXISTS
提供以下计划
添加INSERT INTO A
SELECT *
FROM B
WHERE NOT EXISTS (SELECT 1 FROM A WHERE id = B.id)
子句
A
按如下方式更改计划
除了现在包括反半连接的计划之外,SQL Server还在SELECT
上插入聚簇索引之前向计划添加了一个急切的假脱机。这是一个阻塞运算符,其目的是确保在将任何行插入B
之前评估整个SORT
(与Halloween Protection相关)。
但是,您可能不一定在计划中看到假脱机。例如SQL Server也可能选择使用另一个阻塞运算符,例如{{1}}或散列反半连接。
请至少发布标准版的执行计划,最好是两者。还有查询,所以我们可以看到你是否正在使用任何不确定的结构。
答案 1 :(得分:0)
尝试重构您的查询,看看它是否有效。而不是NOT EXISTS
连接插入查询中的表:
INSERT A(...)
SELECT ... FROM B LEFT JOIN A ON B.id = A.id
WHERE B.id = 45 AND A.id IS NULL
然后您只执行一次选择。