MERGE违反PRIMARY KEY约束

时间:2012-05-23 16:44:38

标签: sql sql-server sql-server-2008 tsql upsert

我有一个SQL Server 2008多对多关系表(Assets),有两列:

AssetId (PK, FK, uniqueidentifier, not null)
AssetCategoryId (PK, FK, int, not null)

在我的项目中,我需要从该表中获取行,并定期将它们插入到复制的数据库中。所以,我有两个完全相同的数据库(包括约束)。

为了从一个数据库“复制”到另一个数据库,我使用带有临时表的MERGE语句。我在临时表中最多插入50条记录,然后将临时表与我正在复制的Assets表合并,如下所示:

CREATE TABLE #Assets (AssetId UniqueIdentifier, AssetCategoryId Int);
INSERT INTO #Assets (AssetId, AssetCategoryId) VALUES ('ed05bac3-7a92-46aa-8822-2d882b137597', 44), ('dc5e3082-e2eb-4bdf-a640-94e0f59411ed', 22) ... ;

MERGE INTO Assets WITH (HOLDLOCK) AS Target 
USING #Assets AS Source 
ON Target.AssetId = Source.AssetId AND Target.AssetCategoryId = Source.AssetCategoryId 
WHEN MATCHED THEN
UPDATE SET ...
WHEN NOT MATCHED BY Target THEN 
INSERT (AssetId,AssetCategoryId) VALUES (Source.AssetId,Source.AssetCategoryId);

这在大多数情况下效果很好。但是,偶尔会出现错误:

  

违反PRIMARY KEY约束'PK_Assets'。无法插入   对象'dbo.Assets'中的重复键。重复的键值是   (dc5e3082-e2eb-4bdf-a640-94e0f59411ed,22)。声明一直如此   终止。

当我签入Assets表时,没有这样的记录......所以我很困惑如何插入重复的密钥。

知道这里发生了什么吗?

更新

测试时,它成功运行6次,插入300行。在第7次尝试时,它总是给出上面显示的相同错误。此外,当我INSERT (dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22)本身时,它可以正常工作。然后我的测试能够继续并插入剩余的行而没有错误。

1 个答案:

答案 0 :(得分:14)

您需要在HOLDLOCK声明中添加MERGE。请尝试以下方法:

MERGE INTO Assets WITH (HOLDLOCK) AS Target
...

这可以避免您遇到的竞争条件。查看更多信息here

修改

根据您的更新,我能想到的另一件事是您的临时表中可能有重复的记录。你能仔细检查吗?