能否在SQL MERGE语句中先执行UPDATE再执行DELETE?
在MERGE语句中实现删除前更新行的需求
我需要优化SQL MERGE语句,要求在删除行之前先对该行执行UPDATE操作。我的Produkt表中UsId列的值有时为NULL,而记录删除行的触发器需要用到UsId的值,所以必须在删除前把UsId更新为有效值。
原有的MERGE语句如下:
MERGE Produkt Target USING (SELECT 9558, 'A000043179', 1.0000) Source (TowId, NosnikId, Opakowanie) ON ( Target.TowId = Source.TowId AND Target.NosnikId = Source.NosnikId AND Target.Opakowanie = Source.Opakowanie) WHEN MATCHED AND Target.Ilosc - 15 * 8.0000 = 0 THEN DELETE WHEN MATCHED THEN UPDATE SET Target.Ilosc = Target.Ilosc - 15 * 8.0000, Target.UsId = 2;
我知道可以在MERGE前单独执行UPDATE语句,但好奇是否能在同一条MERGE语句中实现,比如尝试这样写:
MERGE Produkt AS Target USING (SELECT 9558, 'A000043179', 1.0000) AS Source (TowId, NosnikId, Opakowanie) ON (Target.TowId = Source.TowId AND Target.NosnikId = Source.NosnikId AND Target.Opakowanie = Source.Opakowanie) WHEN MATCHED AND Target.Ilosc - 15 * 8.0000 = 0 THEN /* UPDATE SET Target.UsId = 2 AND/THEN */ DELETE WHEN MATCHED THEN UPDATE SET Target.Ilosc = Target.Ilosc - 15 * 8.0000, Target.UsId = 2;
解决方案
SQL的MERGE语句不支持在同一个WHEN MATCHED分支中先后执行UPDATE和DELETE操作——每个匹配的行只会触发第一个符合条件的分支逻辑,无法在同一个分支里完成两个操作。
如果要满足删除前更新UsId的需求,最直接可靠的方式是拆分操作:先单独更新要删除行的UsId,再执行原MERGE语句。
示例代码:
-- 提前更新即将被删除行的UsId,确保触发器能获取有效值 UPDATE Produkt SET UsId = 2 WHERE TowId = 9558 AND NosnikId = 'A000043179' AND Opakowanie = 1.0000 AND Ilosc - 15 * 8.0000 = 0; -- 执行原MERGE逻辑,处理删除和剩余行的更新 MERGE Produkt Target USING (SELECT 9558, 'A000043179', 1.0000) Source (TowId, NosnikId, Opakowanie) ON ( Target.TowId = Source.TowId AND Target.NosnikId = Source.NosnikId AND Target.Opakowanie = Source.Opakowanie) WHEN MATCHED AND Target.Ilosc - 15 * 8.0000 = 0 THEN DELETE WHEN MATCHED THEN UPDATE SET Target.Ilosc = Target.Ilosc - 15 * 8.0000, Target.UsId = 2;
如果一定要在单个语句中实现,可以考虑使用CTE结合UPDATE和DELETE,但本质上还是拆分了操作,写法如下:
WITH ToDelete AS ( SELECT * FROM Produkt WHERE TowId = 9558 AND NosnikId = 'A000043179' AND Opakowanie = 1.0000 AND Ilosc - 15 * 8.0000 = 0 ) UPDATE ToDelete SET UsId = 2 DELETE FROM ToDelete; -- 再处理剩余行的更新 UPDATE Produkt SET Ilosc = Ilosc - 15 * 8.0000, UsId = 2 WHERE TowId = 9558 AND NosnikId = 'A000043179' AND Opakowanie = 1.0000 AND Ilosc - 15 * 8.0000 <> 0;
不过这种写法已经替代了MERGE的原有逻辑,失去了MERGE语句的简洁性。
综上,最推荐的还是拆分UPDATE和MERGE的方案,逻辑清晰且符合MERGE的语法限制。
内容的提问来源于stack exchange,提问作者Tomek L
相关产品推荐
相关产品推荐

