如果不存在则插入,同时插入

Chr*_*ris 13 sql-server-2008 sql-server concurrency

我在存储过程中的插入有并发问题。该程序的相关部分是这样的:

select @_id = Id from table1 where othervalue = @_othervalue
IF( @_id IS NULL)
BEGIN
    insert into table1 (othervalue) values (@_othervalue)
    select @_id = Id from table1 where othervalue = @_othervalue
END
Run Code Online (Sandbox Code Playgroud)

当我们同时运行 3 个或 4 个这些存储过程时,我们有时会得到多个插入。

我打算像这样解决这个问题:

insert into table1 (othervalue) 
    select TOP(1) @_othervalue as othervalue from table1 WITH(UPDLOCK) 
    where NOT EXISTS ( select * from table1 where othervalue = @_othervalue )

select @_id = Id from table1 where othervalue = @_othervalue
Run Code Online (Sandbox Code Playgroud)

问题是,如何在sql server中并发插入而不重复?我必须使用 TOP 只插入一次的事实让我感到不安。

Mik*_*son 7

您可以使用带有serializable提示的合并语句。

merge table1 with (serializable) as T 
using (select @_othervalue as othervalue) as S
on T.othervalue = S.othervalue
when not matched then
  insert (othervalue) values (othervalue);
Run Code Online (Sandbox Code Playgroud)

  • @AlexKuznetsov - 不久前我做了另一个关于 SO 的问题。我在 SSMS 中使用了两个选项卡。首先测试了 `insert ... where not exist ...` 模式,发现可能会出现死锁和密钥冲突,因此有必要使用 updlock 和可序列化。然后我测试了合并语句,并认为它可以更好地处理事情,因为那里没有死锁,但我仍然必须使用可序列化来避免密钥冲突。 (2认同)

Sta*_*hns 5

如果您不想在“othervalue”列上重复,您可以通过unique constraint在该列上创建一个来实现。查询将是:

 ALTER TABLE table1
 ADD CONSTRAINT unique_c_othervalue UNIQUE(othervalue)
Run Code Online (Sandbox Code Playgroud)

如果查询尝试将重复值插入到“othervalue”列中,这将引发错误。