我试图了解为什么在以下情况下发生这种情况
DECLARE @source TABLE
(
orderId NVARCHAR(50),
customerId NVARCHAR(50)
)
DECLARE @target TABLE
(
orderId NVARCHAR(50) PRIMARY KEY,
customerId NVARCHAR(50) NOT NULL
)
INSERT INTO @source
VALUES ('test', '123'), ('test', '234')
MERGE @target AS TRG
USING (SELECT DISTINCT orderId, customerId
FROM @source) AS SRC ON SRC.orderId = TRG.orderId
WHEN MATCHED THEN
UPDATE SET TRG.customerId = SRC.customerId
WHEN NOT MATCHED BY TARGET THEN
INSERT (orderId, customerId)
VALUES (orderId, customerId);
我收到重复的密钥冲突错误:
第2级第1州第21行2627消息
违反主键约束'PK __#B3D7759__0809335D4BE1521F'。无法在对象“ dbo。@ target”中插入重复密钥。重复的键值为(测试)。
我期望的是update语句找到现有的密钥并更新customerId,以便最后在@target 1行中有orderId ='test'和customerId ='234'。
对于我可以假设的是,它尝试插入所有记录,因为它首先在合并开始时没有找到任何键匹配,从而导致违反,因为源多次包含键。
这是对的吗?有什么方法可以使用合并功能实现我的期望吗?
@ user1443098
我已经阅读了您的链接,谢谢。但是,我从源表中插入了大量数据,并将其插入10个不同的表中。我试图用游标实现该过程,每条记录花费了0.5s的时间(使用所有if存在语句)。使用merge语句,在不到一秒钟的时间内将300行插入了10个不同的表中。因此,就我而言,它在性能方面有很多差异。
答案 0 :(得分:2)
@source
中有两个记录,它们具有相同的OrderID
。 @target
中的任何一条记录都不匹配,因此NOT MATCHED
子句试图插入这两个记录。但这不能这样做,因为OrderID
表中@target
上的主键要求所有插入的记录都具有OrderID
的唯一值。将值复制到主键中会导致违反主键。
如果您期望源中可能存在重复项,则应在USING
子查询中将其消除。像这样:
(SELECT orderId, max(customerId) customerId
FROM @source
group by orderId)