INSERT INTO .. SELECT ..唯一约束违规

sta*_*tan 5 sql sql-server unique-constraint

我正在运行一个存储过程,它选择值我的临时表并将它们插入到数据库中,如下所示:

 INSERT INTO emails (EmailAddress)   (
     SELECT
       DISTINCT eit.EmailAddress
     FROM #EmailInfoTemp eit
       LEFT JOIN emails ea
         ON eit.EmailAddress = ea.EmailAddress
     WHERE ea.EmailAddressID IS NULL   )
Run Code Online (Sandbox Code Playgroud)

在极少数情况下(〜每隔几个小时在服务器上每分钟处理数千个请求),然后我会在EmailAddress列的索引上收到唯一约束错误"违反UNIQUE KEY约束 ..".

我可以确认我没有传递重复的值.即使我是,它应该被DISTINCT捕获.

-SQL Server 2008 -Stored proc +不使用事务+ JDBC callablestatement

可能发生在SELECT和随后的INSERT之间,还有另一个调用相同/不同的存储过程,它完成了一个具有类似数据的INSERT?如果是这样,那么防止这种情况的最佳方法是什么?

一些想法:我们有很多重复的"客户"实例,他们在生产中同时与这一个SQL Server进行通信,所以我的第一反应是并发问题,但我似乎无法自己复制它.这是我最好的猜测,但它到目前为止无处可去.在我们的临时环境中,这种情况不会发生,因为与生产环境相比,负载是无关紧要的.这是我开始研究并发问题的主要原因.

And*_*mar 5

该错误可能是由两个会话同时执行插入引起的.

您可以使用MERGE使SQL代码更安全.正如Aaron Bertrand的评论所说(谢谢!),你必须提供一个非常安全的with (holdlock)提示merge.

; merge emails e with (holdlock)
using   #EmailInfoTemp eit
on      e.EmailAddress = eit.EmailAddress
when    not matched then insert
        (EmailAddress) values (eit.EmailAddress)
Run Code Online (Sandbox Code Playgroud)

merge语句将采取适当的锁定,以确保没有其他会话可以在它的"不匹配"检查和"插入"之间潜入.

如果你不能使用merge,你可以解决客户端的问题.确保没有两个插件同时运行.这通常很容易使用互斥锁或其他同步构造.