【问题标题】:Possible to simulate the mySQL functionality ON DUPLICATE KEY UPDATE with SQL Server可以使用 SQL Server 在 DUPLICATE KEY UPDATE 上模拟 mySQL 功能
【发布时间】:2011-03-21 08:27:42
【问题描述】:

我正在使用 SQL Server 2008,并且希望能够利用类似 mySQL 的 ON DUPLICATE KEY UPDATE 子句的 INSERT 语句

当前的遗留代码执行删除和后续插入,这会遇到来自不同线程的重复键插入的并发问题:

这是我在生产环境中看到的错误:

Violation of PRIMARY KEY constraint 'PK_Audience'. Cannot insert duplicate key in object 'dbo.Audience'.

(sp_ContentUpdate)

主键:

AudienceId, VersionId

有问题的 SQL:

DELETE  FROM  dbo.Audience
WHERE   VersionId = @VersionId

IF  @AudienceXml IS NOT NULL
    BEGIN
    INSERT INTO dbo.Audience (
        VersionId,
        AudienceId,
        CreatedDate,
        CreatedByPersonId,
        )
    SELECT  @VersionId,
            AudienceId,
            GETUTCDATE(),
            @PersonId
                FROM    dbo.Audience
    JOIN    @AudienceXml.nodes('/Audiences/Audience') node(c)
    ON      Audience.AudienceName = c.value('@Name', 'nvarchar(50)')
    END

在事务中包装此 TSQL 似乎可以消除并发问题或通过更改时间来掩盖问题。但是,我认为包装事务实际上并没有解决并发问题。

也许我正在处理这个错误。感谢您的建议。

【问题讨论】:

标签: sql sql-server sql-server-2008 concurrency merge


【解决方案1】:

好吧,比尔打败了我们所有人,但这里有一个示例:

Merge dbo.Audience As target
Using   (
        Select @VersionId As VersionId, AudienceId, GetUtcDate() As CreatedDate, @PersonId As CreatedByPersonId
        From dbo.Audience
            Join @AudienceXml.nodes('/Audiences/Audience') node(c)
                On Audience.AudienceName = c.value('@Name', 'nvarchar(50)')
        )
When Matched Then
    Update 
    Set VersoinId = target.VersionId, Audience = target.AudienceId
        , CreatedDate = target.CreatedDate
        , CreatedByPersionId = target.CreatedByPersonId
When Not Matched Then
    Insert dbo.Audience(VersionId, AudienceId, CreatedDate, CreatedByPersonId)

【讨论】:

  • @Bill Karwin - 谢谢。当你回答时,我觉得他在 Ocean's 11 中试图招募 Saul 时就像 Rusty 的角色。“Thomas,我在你今天早上起床之前就看到了答案。”但是,额外工作的布朗尼点也很好。 :)
  • 你不是缺少一个“on”子句来耦合目标表和源表吗?
【解决方案2】:

您应该阅读有关如何在 Microsoft SQL Server 2008 中使用MERGE 语句的信息。这实际上是处理这种情况的 ANSI/ISO SQL 方式(MySQL 的 ON DUPLICATE KEY 是专有的 MySQL 主义)。

请参阅 MSDN 上 MERGE statement 上的文档。

【讨论】:

    猜你喜欢
    • 2010-11-14
    • 2015-01-20
    • 2012-08-31
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 2018-07-12
    相关资源
    最近更新 更多