SQL中如何在MERGE的NOT MATCHED分支插入多行数据?
嘿,这个问题挺常见的——MERGE语句的每个WHEN分支确实只能执行单条操作,所以你没法直接在WHEN NOT MATCHED THEN里一次性插入两行。不过有两种靠谱的方法能实现你的需求,我给你拆解下:
方法1:扩展源数据实现批量插入
思路是先把你的源表@table扩展成每行对应两条记录(一条IsNew=1,一条IsNew=0),然后让MERGE去匹配这些扩展后的记录,这样不匹配的时候就能自动插入两行。
-- 先扩展源数据,每行生成两条不同IsNew的记录 WITH ExtendedSource AS ( SELECT ID, Content, 1 AS IsNew FROM @table UNION ALL SELECT ID, Content, 0 AS IsNew FROM @table ) MERGE ITEMS AS TARGET USING ExtendedSource AS SOURCE -- 匹配条件要加上IsNew,确保同ID的两条记录独立判断 ON TARGET.[ID] = SOURCE.ID AND TARGET.IsNew = SOURCE.IsNew WHEN MATCHED THEN UPDATE SET TARGET.[Content] = SOURCE.[Content] -- 若记录已存在则更新内容 WHEN NOT MATCHED THEN INSERT (ID, Content, TIME, IsNew) VALUES (SOURCE.ID, SOURCE.Content, GETDATE(), SOURCE.IsNew);
这个方法的优势是用单条MERGE完成所有操作,逻辑更紧凑,而且天然保证操作的原子性。
方法2:用事务包裹MERGE+单独INSERT
如果不想扩展源数据,也可以用事务把MERGE和INSERT操作绑定起来,确保要么都成功要么都失败,避免数据不一致:
BEGIN TRANSACTION; -- 先插入IsNew=1的记录 MERGE ITEMS AS TARGET USING @table AS SOURCE ON TARGET.[ID] = SOURCE.ID AND TARGET.IsNew = 1 WHEN MATCHED THEN UPDATE SET TARGET.[Content] = SOURCE.Content WHEN NOT MATCHED THEN INSERT (ID, Content, TIME, IsNew) VALUES (SOURCE.ID, SOURCE.Content, GETDATE(), 1); -- 再插入IsNew=0的记录,用NOT EXISTS避免重复 INSERT INTO ITEMS (ID, Content, TIME, IsNew) SELECT ID, Content, GETDATE(), 0 FROM @table AS SOURCE WHERE NOT EXISTS ( SELECT 1 FROM ITEMS AS TARGET WHERE TARGET.ID = SOURCE.ID AND TARGET.IsNew = 0 ); COMMIT TRANSACTION;
小提醒
你原语句里的VALUES(ID, TEXT, GETDATE(), 1)应该是笔误吧?TEXT这里应该替换成SOURCE.Content,不然会插入错误的值或者触发语法错误哦。
内容的提问来源于stack exchange,提问作者Ken Kaneki
相关产品推荐
相关产品推荐

