Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 合并违反主键约束_Sql_Sql Server_Sql Server 2008_Tsql_Upsert - Fatal编程技术网

Sql 合并违反主键约束

Sql 合并违反主键约束,sql,sql-server,sql-server-2008,tsql,upsert,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条记录插入临时表,然后将临时表与我要复制到的资产

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

AssetId (PK, FK, uniqueidentifier, not null)
AssetCategoryId (PK, FK, int, not null)
在我的项目中,我需要从此表中获取行,并定期将它们插入到复制的数据库中。因此,我有两个完全相同的数据库(包括约束)

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

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);
这在很大程度上非常有效。但是,偶尔我会遇到这样的错误:

违反主键约束“PK_资产”。无法插入 对象“dbo.Assets”中存在重复键。重复的键值为 (dc5e3082-e2eb-4bdf-a640-94E0F5941ED,22)。声明已被修改 终止

当我签入
资产
表时,不存在这样的记录。。。因此,我很困惑如何插入重复的密钥

知道这是怎么回事吗

更新


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

您需要在
MERGE
语句中添加
HOLDLOCK
。请尝试以下操作:

MERGE INTO Assets WITH (HOLDLOCK) AS Target
...
这样可以避免您遇到的竞争条件。查看更多信息

编辑


根据您的更新,我唯一能想到的是您的临时表中可能有一条重复的记录。您能再检查一下吗?

谢谢您的快速回复。你可能在将来帮我(和其他人)省去了一些头痛,但不幸的是,这并没有解决我的问题。请查看更新后的问题。您是100%正确的。我的临时表中有一个副本。我猜HOLDLOCK建议只是一种奖励!另一方面,我看到添加HOLDLOCK会导致死锁,因此没有免费的午餐。merge语句存在bug。也许你打了一个。请张贴执行计划。