首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >仅当行尚未存在时才插入行

仅当行尚未存在时才插入行
EN

Stack Overflow用户
提问于 2010-08-05 00:56:11
回答 4查看 39.5K关注 0票数 75

我总是使用类似于下面的方法来实现它:

代码语言:javascript
运行
复制
INSERT INTO TheTable
SELECT
    @primaryKey,
    @value1,
    @value2
WHERE
    NOT EXISTS
    (SELECT
        NULL
    FROM
        TheTable
    WHERE
        PrimaryKey = @primaryKey)

...but一旦加载,就会发生主键冲突。这是唯一一个插入到这个表中的语句。那么这是否意味着上面的陈述不是原子的呢?

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

也许我可以将其更改为如下所示:

代码语言:javascript
运行
复制
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)

虽然,也许我使用了错误的锁,或者使用了太多的锁或其他什么。

我在stackoverflow.com上看到过其他问题,答案是"IF (SELECT COUNT(*) ... INSERT“等),但我总是假设(可能是错误的)一条SQL语句是原子的。

有谁有什么想法吗?

EN

回答 4

Stack Overflow用户

发布于 2010-08-05 01:45:14

您可以使用MERGE:

代码语言:javascript
运行
复制
MERGE INTO Target
USING (VALUES (@primaryKey, @value1, @value2)) Source (key, value1, value2)
ON Target.key = Source.key
WHEN MATCHED THEN
    UPDATE SET value1 = Source.value1, value2 = Source.value2
WHEN NOT MATCHED BY TARGET THEN
    INSERT (Name, ReasonType) VALUES (@primaryKey, @value1, @value2)
票数 16
EN

Stack Overflow用户

发布于 2017-05-04 04:28:31

首先,向我们的man @gbn致敬,感谢他对社区的贡献。甚至无法解释我发现自己有多频繁地听从他的建议。

不管怎么说,追星族已经玩够了。

稍微补充一下他的答案,也许可以“增强”它。对于那些像我这样的人来说,在<> 2627场景中做什么会让人感到不安(不,空的CATCH不是一个选择)。我从technet那里找到了这个小金块。

代码语言:javascript
运行
复制
    BEGIN TRY
       INSERT etc
    END TRY
    BEGIN CATCH
        IF ERROR_NUMBER() <> 2627
          BEGIN
                DECLARE @ErrorMessage NVARCHAR(4000);
                DECLARE @ErrorSeverity INT;
                DECLARE @ErrorState INT;

                SELECT @ErrorMessage = ERROR_MESSAGE(),
                @ErrorSeverity = ERROR_SEVERITY(),
                @ErrorState = ERROR_STATE();

                    RAISERROR (
                        @ErrorMessage,
                        @ErrorSeverity,
                        @ErrorState
                    );
          END
    END CATCH
票数 2
EN

Stack Overflow用户

发布于 2010-08-05 00:59:47

我不知道这是否是“官方”的方式,但你可以尝试INSERT,如果失败了,可以退回到UPDATE

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3407857

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档