Sql Server 2005 - 如果不存在则插入

发布于 2024-11-09 10:46:49 字数 743 浏览 0 评论 0原文

互联网上有很多关于这个常见“问题”的信息。

在我看来,以下解决方案

IF NOT EXISTS() BEGIN INSERT INTO (...) END

不是线程安全的,您可能会同意。

但是你能确认将exists放入单选的where子句中就可以解决sql引擎的最高并发问题吗? 够了吗?

insert into Table (columns)
select column1, column2, column3
where not exists (select top 1 1 from Table where something)

应该还有添加一些更高的交易级别或者 这可以在默认值上执行吗:已提交?

这可以在未承诺的水平下工作吗?

谢谢!

//稍后添加

我可以假设两个sql'都是正确的:

1) 设置事务隔离级别可重复读

   IF NOT EXISTS() BEGIN INSERT INTO (...) END

2) 设置事务隔离级别可重复读

insert into Table (columns)
select column1, column2, column3
where not exists (select top 1 1 from Table where something)

There is lots of information in the internet regarding this common "problem".

Solutions like:

IF NOT EXISTS() BEGIN INSERT INTO (...) END

are not thread-safe in my opinion and you will probably agree.

However could you confirm that putting the exist into the where clause of one single select would solve the problem of the highest concurrency in sql engine?
Is it enough?

insert into Table (columns)
select column1, column2, column3
where not exists (select top 1 1 from Table where something)

Should be there also added some higher transaction level or
can this be executed on a default one: committed?

Would this work under uncommitted level?

Thanks!

//Added later

Can i assume that both sql' are correct:

1)
set transaction isolation level repeatable read

   IF NOT EXISTS() BEGIN INSERT INTO (...) END

2) set transaction isolation level repeatable read

insert into Table (columns)
select column1, column2, column3
where not exists (select top 1 1 from Table where something)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明天过后 2024-11-16 10:46:49

使用 TRY/CATCH,您可以避免额外的读取

BEGIN TRY
   INSERT etc
END TRY
BEGIN CATCH
    IF ERROR_NUMBER() <> 2627
      RAISERROR etc
END CATCH
  • A NOT EXISTS 将读取表,无论是在 IF 还是 WHERE 中
  • INSERT 需要读取来检查唯一性

如果您可以丢弃重复项,这是一种高度可扩展的技术

链接:

With TRY/CATCH you can avoid the extra read

BEGIN TRY
   INSERT etc
END TRY
BEGIN CATCH
    IF ERROR_NUMBER() <> 2627
      RAISERROR etc
END CATCH
  • A NOT EXISTS will read the table, whether in the IF or WHERE
  • The INSERT requires a read to check uniqueness

If you can discard duplicates, this is a highly scalable technique

Links:

莫多说 2024-11-16 10:46:49

要回答更新后的问题可重复读取仍然不够。

您需要的是 holdlock / serialized 级别。

您正在尝试防止幻像(第一次读取时没有遇到行)条件,因此 NOT EXISTS 返回 true,但随后并发事务插入满足该条件的行)

To answer the updated question repeatable read would still not be sufficient.

It is holdlock / serializable level that you would need.

You are trying to prevent phantoms (where on the first read no rows met the criteria so the NOT EXISTS returns true but subsequently a concurrent transaction inserts a row meeting it)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文