简体   繁体   English

MERGE违反PRIMARY KEY约束

[英]MERGE Violation of PRIMARY KEY constraint

I have a SQL Server 2008 many-to-many relationship table ( Assets ) with two columns: 我有一个SQL Server 2008多对多关系表( Assets ),有两列:

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

In my project, I need to take rows from this table, and insert them into a replicated database periodically. 在我的项目中,我需要从该表中获取行,并定期将它们插入到复制的数据库中。 So, I have two databases that are exactly the same (constraints included). 所以,我有两个完全相同的数据库(包括约束)。

In order to "copy" from one database to the other, I use a MERGE statement with a temp table. 为了从一个数据库“复制”到另一个数据库,我使用带有临时表的MERGE语句。 I insert up to 50 records into the temp table, then merge the temp table with the Assets table I am copying into as follows: 我将最多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);

This works great, for the most part. 在大多数情况下,这很有效。 However, once in a while, I get the error: 但是,偶尔会出现错误:

Violation of PRIMARY KEY constraint 'PK_Assets'. 违反PRIMARY KEY约束'PK_Assets'。 Cannot insert duplicate key in object 'dbo.Assets'. 无法在对象'dbo.Assets'中插入重复键。 The duplicate key value is (dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22). 重复键值为(dc5e3082-e2eb-4bdf-a640-94e0f59411ed,22)。 The statement has been terminated. 该语句已终止。

When I check in the Assets table, no such record exists... so I am confused how I would be inserting a duplicate key. 当我签入Assets表时,没有这样的记录......所以我很困惑我将如何插入一个重复的密钥。

Any idea what is going on here? 知道这里发生了什么吗?

UPDATE UPDATE

When testing, it runs successfully 6 times, inserting 300 rows. 测试时,它成功运行6次,插入300行。 On the 7th try, it always gives the same error shown above. 在第7次尝试时,它总是给出上面显示的相同错误。 Furthermore, when I INSERT (dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22) by itself, it works fine. 此外,当我(dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22) INSERT (dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22) ,它工作正常。 My test is then able to continue and insert the remaining rows with no errors. 然后我的测试能够继续并插入剩余的行而没有错误。

You need to add a HOLDLOCK on your MERGE statement. 您需要在MERGE语句中添加HOLDLOCK Try the following: 请尝试以下方法:

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

This avoids the race condition that you are running into. 这可以避免您遇到的竞争条件。 See more info here 在这里查看更多信息

EDIT 编辑

Based on your update, the only other thing I can think of is that your temp table might have a duplicate record in it. 根据您的更新,我能想到的另一件事是您的临时表中可能有重复的记录。 Can you double check? 你能仔细检查吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM