避免SQL Merge Update语句上的密钥冲突

时间:2016-04-25 04:23:17

标签: sql sql-server tsql

我有一个包含两列的表,Prime_GuestID和Dup_GuestID,用于指示GuestID和正在替换的ID之间的链接(重复记录)

现在我想查看格式的许多其他关系表,并将Dup_GuestID的任何出现更新为Prime_GuestID。

但是,如果Prime_GuestID已经有给定ThingID的条目,那么我需要从关系表中删除该行。

目前我正在使用以下脚本,虽然它适用于大多数情况但如果两个Dup_GuestID更新为给定ThingID的相同Prime_GuestID,则会失败。似乎merge语句在进行之前将所有更改排队,因此我的冲突检查不会检测到它们。

MERGE Thing_Relation AS t
USING Guest_Relation AS g
    ON t.GuestID = g.Dup_GuestID
WHEN MATCHED AND EXISTS (  -- Clash Check here
                        select * 
                        from Thing_Relation AS t2 
                        where t2.ThingID = t.ThingID 
                        and t2.GuestID = g.Prime_GuestID
                        ) 
 THEN DELETE
WHEN MATCHED 
 THEN UPDATE SET t.GuestID = g.Prime_GuestID

是否有更好的方法在“匹配并存在时”进行检查以检查此合并可能导致的冲突?或者有更好的方法来完成这一切吗?

编辑:这是表格的一些示例数据

Thing_Relation          Guest_Relation
ThingID | GuestID       Prime_GuestID | Dup_GuestID
------------------      ---------------------------
1       | 101                     101 | 102
1       | 102                     107 | 104
2       | 103                     107 | 105
3       | 104
3       | 105

Thing_Relation after merge
ThingID | GuestID       
------------------      
1       | 101              
2       | 103
3       | 107      

1 | 102变为1 | 101已经存在,因此删除了行。 2 | 103不受影响 3 | 104更改为3 | 107,并且由于3 | 105也更改为3 | 107,但之前的更新尚未发生,但EXISTS子句未将其更新。

1 个答案:

答案 0 :(得分:0)

你是对的,MERGE不会对MERGE语句本身所做的更改进行检查。这是MERGE的基本属性。几个选项可能是:

  1. 在UPDATE上创建一个TRIGGER,它将继续检查每次更新时的冲突并删除重复的行。 OR
  2. 只需为UPDATE编写两个不同的语句,稍后为重复条目编写一个DELETE。