我正在使用SQL Server 2008,并且希望能够利用mySQL的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似乎要么删除并发问题,要么通过更改时间来掩盖问题。但是,我不认为事务中的包装实际上已经解决了并发问题。
也许我正在犯这个错误。您的建议表示赞赏。
答案 0 :(得分:10)
好吧,比尔击败了我们所有人,但这里有一个样子的样本:
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)
答案 1 :(得分:8)
您应该阅读有关如何在Microsoft SQL Server 2008中使用MERGE
语句的信息。这实际上是ANSI / ISO SQL处理这种情况的方式(MySQL的ON DUPLICATE KEY是专有的MySQLism)。
请参阅MSDN上MERGE
statement上的文档。