【发布时间】:2015-09-25 05:29:14
【问题描述】:
我无法找到这个问题的答案。假设我有以下表/查询:
桌子:
create table ##table
(
column1 int,
column2 nvarchar(max)
)
查询(在现实生活场景中,条件会更复杂):
declare @shouldInsert bit
set @shouldInsert = case when exists(
select *
from ##table
where column2 = 'test') then 1 else 0 end
--Exaggerating a possible delay:
waitfor delay '00:00:10'
if(@shouldInsert = 0)
insert into ##table
values(1, 'test')
如果我同时运行此查询两次,则可能会插入重复记录(强制执行唯一约束是不可能的,因为实际条件比表中的“column1”唯一性更复杂)
我看到了两种可能的解决方案:
我在可序列化模式下运行两个并发事务,但它会产生死锁(首先是 select 中的共享锁,然后是插入中的 x 锁 - 死锁)。
1234563 /p>
哪个更容易接受?有第三种解决方案吗?
谢谢。
【问题讨论】:
-
你不能只使用 LEFT JOIN
insert into ##table SELECT t.col1, t.col2 FROM (SELECT 1 as col1, 'test' as col2) t LEFT JOIN ##table temp ON t.col1 = temp.col1 WHERE temp.col1 IS NULL? -
您是否考虑过将 shouldInsert 测试和实际插入合并到单个 SQL 语句中。类似于“插入##table(select 1,'test' from dual where not exist ...”的内容)
-
我会选择第二种解决方案,但在子查询中使用带有锁定提示的
INSERT...SELECT...WHERE NOT EXISTS语法。我不认为并发是一个问题,除非你有一个非常高的插入率,假设 column2 上有一个唯一的索引。
标签: sql-server database