Chr*_*nce 9 sql sql-server concurrency merge sql-server-2008
我正在使用SQL Server 2008,并希望能够利用类似mySQL的ON DUPLICATE KEY UPDATE
子句来进行INSERT
语句
当前遗留代码执行删除和后续插入,该插入遇到并发问题,并且来自不同线程的重复键插入:
这是我在生产环境中看到的错误:
Violation of PRIMARY KEY constraint 'PK_Audience'. Cannot insert duplicate key in object 'dbo.Audience'.
Run Code Online (Sandbox Code Playgroud)
(sp_ContentUpdate)
首要的关键:
AudienceId, VersionId
Run Code Online (Sandbox Code Playgroud)
违反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
Run Code Online (Sandbox Code Playgroud)
在事务中包装此TSQL似乎要么删除并发问题,要么通过更改时间来掩盖问题.但是,我不认为事务中的包装实际上已经解决了并发问题.
也许我错了.您的建议表示赞赏.
Tho*_*mas 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)
Run Code Online (Sandbox Code Playgroud)