SQL中的MERGE语句是一种用于合并两个数据表数据的专用语句,它可以根据源表和目标表的匹配结果,自动执行插入、更新或者删除操作,不需要开发者编写多段逻辑分别处理不同情况,大幅简化了数据同步、增量更新等场景的代码复杂度。

MERGE语句的核心逻辑
MERGE语句的执行流程可以分为三个核心步骤:
- 首先指定目标表,也就是需要被修改的数据表
- 然后指定源表,也就是提供新数据的来源表,同时定义两个表的匹配条件
- 最后根据匹配结果定义不同的操作:匹配成功时执行更新或删除,匹配失败时执行插入
标准MERGE语法结构
SQL标准中的MERGE语句基本结构如下:
MERGE INTO 目标表 AS target
USING 源表 AS source
ON target.匹配字段 = source.匹配字段
-- 匹配成功时的操作
WHEN MATCHED THEN
UPDATE SET target.字段1 = source.字段1, target.字段2 = source.字段2
-- 匹配失败时的操作
WHEN NOT MATCHED THEN
INSERT (字段1, 字段2) VALUES (source.字段1, source.字段2);
不同数据库中的使用示例
SQL Server中的MERGE使用
假设我们有用户基础表user_base和用户更新表user_update,需要将更新表的数据同步到基础表,存在则更新手机号,不存在则插入新用户:
-- 创建目标表
CREATE TABLE user_base (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
phone VARCHAR(20)
);
-- 创建源表
CREATE TABLE user_update (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
phone VARCHAR(20)
);
-- 插入测试数据
INSERT INTO user_base VALUES (1, '张三', '13800000000');
INSERT INTO user_update VALUES (1, '张三', '13800001111'), (2, '李四', '13900000000');
-- 执行MERGE操作
MERGE INTO user_base AS target
USING user_update AS source
ON target.user_id = source.user_id
WHEN MATCHED THEN
UPDATE SET target.user_name = source.user_name, target.phone = source.phone
WHEN NOT MATCHED THEN
INSERT (user_id, user_name, phone) VALUES (source.user_id, source.user_name, source.phone);
Oracle中的MERGE使用
Oracle的MERGE语法和标准语法基本一致,同样实现上述用户数据同步的逻辑:
MERGE INTO user_base target
USING user_update source
ON (target.user_id = source.user_id)
WHEN MATCHED THEN
UPDATE SET target.user_name = source.user_name, target.phone = source.phone
WHEN NOT MATCHED THEN
INSERT (user_id, user_name, phone) VALUES (source.user_id, source.user_name, source.phone);
常见应用场景
- 增量数据同步:将业务系统的增量数据同步到数据仓库,避免全量覆盖带来的性能问题
- 数据去重合并:将多个来源的同结构数据合并到一张表,自动处理重复记录
- 配置表更新:系统配置表需要定期更新,使用MERGE可以一次性完成新增和已有配置的修改
- 缓存数据刷新:将数据库最新数据同步到缓存表,保持缓存和源数据的一致性
使用注意事项
- 不同数据库对MERGE的支持程度不同,MySQL目前没有原生MERGE语句,需要使用
INSERT ... ON DUPLICATE KEY UPDATE替代 - 匹配条件建议选择唯一索引字段,避免单次MERGE操作匹配到多条记录导致执行错误
- 如果源表数据量较大,建议提前对匹配字段建立索引,提升MERGE语句的执行效率
- 执行前可以先使用SELECT语句验证匹配逻辑,避免误操作修改错误数据
需要注意的是,MERGE语句执行时会加锁,在业务高峰期操作大表时,建议分批次执行,避免影响线上业务的正常运行。