仅在行不存在时才插入行

Only inserting a row if it#39;s not already there(仅在行不存在时才插入行)
本文介绍了仅在行不存在时才插入行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直使用类似于以下的东西来实现它:

I had always used something similar to the following to achieve it:

INSERT INTO TheTable
SELECT
    @primaryKey,
    @value1,
    @value2
WHERE
    NOT EXISTS
    (SELECT
        NULL
    FROM
        TheTable
    WHERE
        PrimaryKey = @primaryKey)

...但是一旦在负载下,就会发生主键冲突.这是唯一插入该表的语句.那么这是否意味着上面的语句不是原子的呢?

...but once under load, a primary key violation occurred. This is the only statement which inserts into this table at all. So does this mean that the above statement is not atomic?

问题是这几乎不可能随意重新创建.

The problem is that this is almost impossible to recreate at will.

也许我可以将其更改为以下内容:

Perhaps I could change it to the something like the following:

INSERT INTO TheTable
WITH
    (HOLDLOCK,
    UPDLOCK,
    ROWLOCK)
SELECT
    @primaryKey,
    @value1,
    @value2
WHERE
    NOT EXISTS
    (SELECT
        NULL
    FROM
        TheTable
    WITH
        (HOLDLOCK,
        UPDLOCK,
        ROWLOCK)
    WHERE
        PrimaryKey = @primaryKey)

不过,也许我使用了错误的锁或使用了太多的锁等.

Although, maybe I'm using the wrong locks or using too much locking or something.

我在 stackoverflow.com 上看到了其他问题,其中的答案建议使用IF (SELECT COUNT(*) ... INSERT"等,但我一直处于(可能不正确的)假设下,即单个 SQL 语句会是原子的.

I have seen other questions on stackoverflow.com where answers are suggesting a "IF (SELECT COUNT(*) ... INSERT" etc., but I was always under the (perhaps incorrect) assumption that a single SQL statement would be atomic.

有人有什么想法吗?

推荐答案

"JFDI"怎么样模式?

BEGIN TRY
   INSERT etc
END TRY
BEGIN CATCH
    IF ERROR_NUMBER() <> 2627
      RAISERROR etc
END CATCH

说真的,这是最快的,并且在没有锁的情况下并发最多,尤其是在大容量时.如果UPDLOCK升级,整个表都被锁定了怎么办?

Seriously, this is quickest and the most concurrent without locks, especially at high volumes. What if the UPDLOCK is escalated and the whole table is locked?

阅读第四课:

第 4 课:在调整索引之前开发 upsert proc 时,我首先相信 If Exists(Select…) 行会针对任何项目触发,并且会禁止重复.纳达.在很短的时间内有数千个重复项,因为相同的项目会在相同的毫秒内命中 upsert,并且两个事务都会看到不存在并执行插入.经过大量测试后,解决方案是使用唯一索引,捕获错误,然后重试允许事务查看行并执行更新而不是插入.

Lesson 4: When developing the upsert proc prior to tuning the indexes, I first trusted that the If Exists(Select…) line would fire for any item and would prohibit duplicates. Nada. In a short time there were thousands of duplicates because the same item would hit the upsert at the same millisecond and both transactions would see a not exists and perform the insert. After much testing the solution was to use the unique index, catch the error, and retry allowing the transaction to see the row and perform an update instead an insert.

这篇关于仅在行不存在时才插入行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Execute complex raw SQL query in EF6(在EF6中执行复杂的原始SQL查询)
Hibernate reactive No Vert.x context active in aws rds(AWS RDS中的休眠反应性非Vert.x上下文处于活动状态)
Bulk insert with mysql2 and NodeJs throws 500(使用mysql2和NodeJS的大容量插入抛出500)
Flask + PyMySQL giving error no attribute #39;settimeout#39;(FlASK+PyMySQL给出错误,没有属性#39;setTimeout#39;)
auto_increment column for a group of rows?(一组行的AUTO_INCREMENT列?)
Sort by ID DESC(按ID代码排序)