【问题标题】:SQL Server how read a record and then write if it is not there without creating duplicatesSQL Server如何读取记录,然后在不存在的情况下写入而不创建重复项
【发布时间】:2012-07-26 15:52:30
【问题描述】:

如果表中还没有记录,有哪些更好的技术可以将其插入到表中?

问题在于代码会检查符合条件的记录是否存在,如果不存在,则会创建一条。但是,第二个线程可能会同时出现并检查。

我们开始尝试使用 TABLOCKX,它最初可以工作,虽然感觉有点像使用大象枪,但我们也在考虑使用快照隔离,它在这种情况下不起作用,第二个事务可能刚刚到来一起阅读表格。

这是一个常见的问题,所以看起来应该有一个更标准的解决方案。请注意,此处不适合使用唯一索引,因为正在搜索的字段可能包含空值,并且 SQL Server 2005 不支持该上下文中的唯一约束。

【问题讨论】:

  • 如果您使用 SQL Server 2008,那么您也可以查看MERGE

标签: multithreading tsql sql-server-2005 jdbc


【解决方案1】:

我在最初的问题中没有看到任何关于更新表格的内容,所以也许你只想要这样的东西:

INSERT mytable (c1, c2, c3)
SELECT v1, v2, v3
WHERE NOT EXISTS (SELECT 1 FROM mytable WITH (UPDLOCK) WHERE c1=v1 AND c2=v2 AND c3=v3)

【讨论】:

  • 谢谢,绝对是一个解决方案,尽管我必须看看它是多么真实。理论上,第二个线程和连接可以在不存在查找和插入之间做一些事情。我不确定 SQL Server 会阻止这种情况吗?
  • 你是对的,它不能保证防止重复插入。我将更改答案以在子查询中包含 WITH (UPDLOCK)。此外,即使您对更新不感兴趣,您也可以使用 MERGE 语句,匹配条件为 1=0,并且只有一个 WHEN NOT MATCHED 部分,它会在没有提示的情况下正确处理并发。
【解决方案2】:

在 SQL 2008 内部,我建议使用 Merge;但是,您标记了 2005。因此,对于 MS SQL 2005,您最好的选择是使用事务:

我会使用这样的东西:

begin tran
   update table with (x) set ...
   where key = @key

   if @@rowcount = 0
   begin
          insert table (key, ...) values (@key,..)
   end
commit tran

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-19
    • 1970-01-01
    • 2015-04-25
    • 2011-06-04
    • 1970-01-01
    • 1970-01-01
    • 2023-01-02
    • 1970-01-01
    相关资源
    最近更新 更多