SQL Server合并和pk违反

时间:2018-11-27 21:44:50

标签: sql-server merge primary-key

我试图了解为什么在以下情况下发生这种情况

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个不同的表中。因此,就我而言,它在性能方面有很多差异。

1 个答案:

答案 0 :(得分:2)

@source中有两个记录,它们具有相同的OrderID@target中的任何一条记录都不匹配,因此NOT MATCHED子句试图插入这两个记录。但这不能这样做,因为OrderID表中@target上的主键要求所有插入的记录都具有OrderID的唯一值。将值复制到主键中会导致违反主键。

如果您期望源中可能存在重复项,则应在USING子查询中将其消除。像这样:

(SELECT orderId, max(customerId) customerId
FROM @source
group by orderId)