MERGE 是 Oracle 数据库提供的一种强大 SQL 语句,能在单条语句中同时执行插入和更新操作。以下通过一个典型场景来理解其用法:
需求示例:将 T1 表数据更新到 T2 表中,满足以下条件:
如果 T2 表的 NAME 在 T1 表中已存在,则将 MONEY 累加
如果 T2 表的 NAME 在 T1 表中不存在,则将 T1 表的记录插入到 T2 表

表结构初始化:
DROP TABLE T1;
CREATE TABLE T1 (NAME VARCHAR2(20),MONEY NUMBER);
INSERT INTO T1 VALUES ('A',10);
INSERT INTO T1 VALUES ('B',20);
DROP TABLE T2;
CREATE TABLE T2 (NAME VARCHAR2(20),MONEY NUMBER);
INSERT INTO T2 VALUES ('A',30);
INSERT INTO T2 VALUES ('C',20);
COMMIT;
传统实现这一需求,需要使用 UPDATE 和 INSERT 两条 SQL 语句,或使用 PL/SQL 编写复杂的业务逻辑。而 MERGE 语句可以一步到位完成:
MERGE INTO T2 USING T1 ON (T1.NAME=T2.NAME) WHEN MATCHED THEN UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY WHEN NOT MATCHED THEN INSERT VALUES (T1.NAME,T1.MONEY);
**MERGE 语句同样支持执行计划分析:**
SQL> explain plan for
2 MERGE INTO T2
3 USING T1
4 ON (T1.NAME=T2.NAME)
5 WHEN MATCHED THEN
6 UPDATE
7 SET T2.MONEY=T1.MONEY+T2.MONEY
8 WHEN NOT MATCHED THEN
9 INSERT
10 VALUES (T1.NAME,T1.MONEY);
Explained
SQL> SELECT * FROM table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------
Plan hash value: 2414655244
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 2 | 152 | 7 (15)| 00:00:01 |
| 1 | MERGE | T2 | | | | |
| 2 | VIEW | | | | | |
|* 3 | HASH JOIN OUTER | | 2 | 124 | 7 (15)| 00:00:01 |
| 4 | TABLE ACCESS FUL L | T1 | 2 | 50 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | T2 | 2 | 74 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("T1"."NAME"="T2"."NAME"(+))
Note
-----
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------
- dynamic sampling used for this statement
21 rows selected
从执行计划可见,Oracle 内部通过外连接(HASH JOIN OUTER)实现了MERGE操作,先全表扫描两个表,再进行数据处理。
MERGE语法结构
标准语法如下:
MERGE [hint] INTO [schema .] table [t_alias]
USING [schema .] { table | view | subquery } [t_alias]
ON ( condition ) WHEN MATCHED THEN merge_update_clause
WHEN NOT MATCHED THEN merge_insert_clause;
Oracle 10g 之后,MERGE 语句功能得到了显著增强:
仅执行 UPDATE 操作:
SQL> MERGE INTO T2 2 USING T1 3 ON (T1.NAME=T2.NAME) 4 WHEN MATCHED THEN 5 UPDATE 6 SET T2.MONEY=T1.MONEY+T2.MONEY; Done
仅INSERT操作
SQL> MERGE INTO T2 2 USING T1 3 ON (T1.NAME=T2.NAME) 4 WHEN NOT MATCHED THEN 5 INSERT 6 VALUES (T1.NAME,T1.MONEY); Done
这种灵活性使得MERGE能够适应更多场景,避免编写多余的业务逻辑。
MERGE操作支持添加WHERE子句进行精细控制:
SQL> MERGE INTO T2 2 USING T1 3 ON (T1.NAME=T2.NAME) 4 WHEN MATCHED THEN 5 UPDATE 6 SET T2.MONEY=T1.MONEY+T2.MONEY 7 WHERE T1.NAME='A' ---此处表示对MERGE的条件进行过滤 8 ; Done
这使得我们可以在匹配的记录中再次筛选,只对符合特定条件的记录执行操作。
在满足匹配条件的记录中,可以增加删除操作:
MERGE INTO T2 USING T1 ON (T1.NAME=T2.NAME) WHEN MATCHED THEN UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY DELETE WHERE (T2.NAME = 'A') ;
注意:DELETE 只处理满足 ON 条件(T1.NAME = T2.NAME)的记录,如果 T2.NAME = 'A' 不在满足条件的记录集中,DELETE 不会生效。
通过设置永不满足的 ON 条件(如 1=2),可实现类似 INSERT...SELECT 的批量插入功能:
SQL> MERGE INTO T2 2 USING T1 3 ON (1=2) 4 WHEN NOT MATCHED THEN 5 INSERT 6 VALUES (T1.NAME,T1.MONEY); Done
这种技巧可以让MERGE在不执行任何UPDATE操作的情况下,高效地完成批量数据插入。

MERGE语句是Oracle数据库中处理数据整合的强大工具,通过单一语句实现多种数据操作,具有以下核心优势:
简化代码:用一条SQL语句替代多条语句或复杂PL/SQL逻辑
提高效率:减少数据库交互次数,降低网络开销
增强可读性:业务逻辑更加清晰,易于维护
灵活操作:支持条件筛选、可选择性执行不同操作、支持DELETE功能
随着数据处理需求的日益复杂,掌握MERGE这一强大工具能显著提升开发效率和性能。下篇将深入探讨MERGE的高级用法和性能优化技巧。
未完待续...
公众号:收获不止数据库
微信:ljbyxl1213
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9091385/viewspace-3090183/ ,如需转载,请注明出处,否则将追究法律责任。