在写数据层逻辑时,我们常需要把一张源表的数据同步到目标表。如果目标表里的主键已经存在,就更新对应字段;不存在才插入新行。把这种判断放进SQL存储过程,并用MERGE INTO语法来实现,可以让数据库自己完成匹配和分支处理。

什么是MERGE INTO
MERGE INTO是一种标准SQL语句,能够根据源表与目标表的连接条件,决定对目标表执行插入还是更新。它特别适合放在存储过程里处理主键冲突场景,避免应用层先查后写的额外往返。
在存储过程中使用MERGE INTO
下面以Oracle风格语法为例,演示一个存储过程,把临时表tmp_user的数据合并进user_info表。当user_id主键冲突时更新姓名和年龄,否则插入新记录。
CREATE OR REPLACE PROCEDURE merge_user_data AS
BEGIN
MERGE INTO user_info t
USING tmp_user s
ON (t.user_id = s.user_id)
WHEN MATCHED THEN
UPDATE SET t.user_name = s.user_name,
t.age = s.age
WHEN NOT MATCHED THEN
INSERT (user_id, user_name, age)
VALUES (s.user_id, s.user_name, s.age);
COMMIT;
END merge_user_data;
关键语法说明
- ON子句:指定主键或唯一键的匹配条件,这里是user_id相等。
- WHEN MATCHED:主键冲突时走更新分支。
- WHEN NOT MATCHED:未冲突时走插入分支。
在MySQL中的替代写法
MySQL没有MERGE INTO,但可以用INSERT ... ON DUPLICATE KEY UPDATE达到同样效果。下面逻辑等价:
CREATE PROCEDURE merge_user_data()
BEGIN
INSERT INTO user_info (user_id, user_name, age)
SELECT user_id, user_name, age FROM tmp_user
ON DUPLICATE KEY UPDATE
user_name = VALUES(user_name),
age = VALUES(age);
END;
注意事项
使用MERGE INTO时要注意并发事务隔离级别,避免多个会话同时合并同一主键造成锁等待。另外源表数据应保证主键唯一,否则USING部分会出现重复匹配行,导致更新分支被执行多次。
把合并逻辑下沉到存储过程,既能减少网络交互,也能利用数据库引擎的优化器生成更高效执行计划。
小结
通过SQL存储过程封装MERGE INTO(或对应数据库的等价语法),可以用一条语句解决主键冲突时的自动更新问题,代码更清晰,执行也更可靠。
SQL存储过程MERGE_INTO主键冲突修改时间:2026-07-29 16:30:21