SQL Server 2016 Merge语句覆盖4种场景时场景4失效求解
问题排查及解决方案
问题根源
原有MERGE语句仅以TaskId作为唯一匹配条件,当场景4中同TaskId的目标记录已处理(IsProcessed=1)且指标变更时,会被判定为匹配成功,仅会走更新分支而无法触发插入逻辑,因此场景4无法正常执行。
适配全场景的MERGE实现方案
调整匹配逻辑,将「已处理记录的指标是否一致」加入匹配规则,同时保留原有更新逻辑:
MERGE Wrike_Task_Kimble_Log AS TARGET USING temp_Wrike_Kimble AS SOURCE -- 调整匹配规则:同TaskId下,未处理记录直接匹配,已处理记录需同时满足两个Margin相等才匹配 ON ( TARGET.TaskId = SOURCE.TaskId AND ( TARGET.IsProcessed = 0 OR ( TARGET.IsProcessed = 1 AND TARGET.ActualMargin = SOURCE.ActualMargin AND TARGET.BudgetMargin = SOURCE.BudgetMargin ) ) ) -- 匹配到且符合更新条件时仅更新Rootpid,适配场景1 WHEN MATCHED AND TARGET.Rootpid <> SOURCE.Rootpid AND TARGET.IsProcessed = SOURCE.IsProcessed THEN UPDATE SET TARGET.Rootpid = SOURCE.Rootpid -- 未匹配时全部插入,同时适配场景3、场景4 WHEN NOT MATCHED BY TARGET THEN INSERT (TaskId,Wrike_Update_Task_URL,ActualMargin,BudgetMargin,IsProcessed,Rootpid) VALUES (SOURCE.TaskId, SOURCE.Wrike_Update_Task_URL,SOURCE.ActualMargin,SOURCE.BudgetMargin,SOURCE.IsProcessed,SOURCE.Rootpid) OUTPUT $action, INSERTED.TaskId AS TargetTaskId, INSERTED.Wrike_Update_Task_URL AS TargetWrike_Update_Task_URL, INSERTED.ActualMargin AS TargetActualMargin, INSERTED.BudgetMargin AS TargetBudgetMargin, INSERTED.IsProcessed AS TargetIsProcessed, INSERTED.Rootpid AS TargetRootpid; SELECT @@ROWCOUNT;
场景适配验证
- 场景1:目标记录未处理(
IsProcessed=0),会被判定为匹配成功,满足更新条件时仅更新Rootpid,符合要求 - 场景2:目标记录已处理且两个Margin与源表一致,会被判定为匹配成功,但
IsProcessed与源表不相等,不会触发更新,也不会触发插入,直接忽略,符合要求 - 场景3:源表
TaskId在目标表不存在,判定为未匹配,直接插入,符合要求 - 场景4:目标记录已处理但两个Margin与源表不一致,判定为未匹配,直接插入新记录,符合要求
注意事项
如果源表temp_Wrike_Kimble存在多条相同TaskId的记录,建议先对源表做去重处理,可通过ROW_NUMBER()窗口函数取最新记录再参与MERGE运算,避免报错。
内容的提问来源于stack exchange,提问作者Vikas J
相关产品推荐
相关产品推荐

