开发者

Possible to simulate the mySQL functionality ON DUPLICATE KEY UPDATE with SQL Server

开发者 https://www.devze.com 2023-01-08 18:59 出处:网络
I am using SQL Server 2008, and would like to be able to take advantage of something like mySQL\'s ON DUPLICATE KEY UPDATE clause for INSERT statements

I am using SQL Server 2008, and would like to be able to take advantage of something like mySQL's ON DUPLICATE KEY UPDATE clause for INSERT statements

Current legacy code does a delete and subsequent insert that is running into concurrency issues with duplicate key inserts from separate threads:

Here is the error I see in my production environment:

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

(sp_ContentUpdate)

Primary Key:

AudienceId, VersionId

Offending 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

Wrapping this TSQL in a transaction seems to either remove the concurrency issue or mask the issue by changing the timings. However, I do not think wrapping in a transaction has actually solved the concurrency.

Perhaps I am going about this wrong. Your suggestions are appreciated.


Well, Bill beat us all, but here's a sample of what it might look like:

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)


You should read about how to use the MERGE statement in Microsoft SQL Server 2008. This is actually the ANSI/ISO SQL way of handling this situation (MySQL's ON DUPLICATE KEY is a proprietary MySQLism).

See docs on the MERGE statement at MSDN.

0

精彩评论

暂无评论...
验证码 换一张
取 消