oracle之merge的深入介绍

本文详细介绍了Oracle数据库中的MERGE语句,包括其基本概念、语法结构及实际应用场景。MERGE允许在一个SQL语句中同时执行INSERT和UPDATE操作,提高了数据处理效率。文章还提供了具体的例子来演示如何使用MERGE进行数据同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章概要:
1.merge的详细介绍
2.merge的语法结构
3.与merge相关的例题
4.相关参考网址
文章内容:
1.merge的详细介绍
MERGE语句是Oracle9i新增的语法,
你能够在一个SQL语句中对一个表同时执行inserts和updates操作.

连接条件匹配上的进行UPDATE,无法匹配的执行INSERT。
这个语法仅需要一次全表扫描就完成了全部工作,执行效率要高于INSERT+UPDATE。
Oracle 10g中MERGE有如下一些改进:

1、UPDATE或INSERT子句是可选的

2、UPDATE和INSERT子句可以加WHERE子句

3、ON条件中使用常量过滤谓词来insert所有的行到目标表中,不需要连接源表和目标表

4、UPDATE子句后面可以跟DELETE子句来去除一些不需要的行

前提:
使用MERGE的前提条件,你必须有INSERT和UPDATE该表的权限,若DELETE时,必须要有DELETE的权限
USING相关:
在用USING时,可以是表,视图或查询结果
MERGE_UPDATE相关:
当满足ON的条件,UPDATE才会更新表。当定义WHERE时,只有满足该条件的行才会更新表,当不满足条件时,会跳过改行。
你不能更新ON里含有的字段
INSERT相关
当不满足ON的条件 会触发INSERT,若后面跟WHERE,则当满足该条件时,触发插入操作。
ERROR_LOGGING_CLAUSE相关

2.merge的语法结构
MERGE [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;
这里写图片描述
这里写图片描述
这里写图片描述

3.与merge相关的例题
我有一个会员表,里面的内容是别处的另外一个应用所管理的。这个应用会定期插入到一张临时表,表示哪些会员需要被增/删/改:

create table plch_members (
id integer primary key
, name varchar2(10) not null
)
/

create table plch_members_stage (
id integer primary key
, name varchar2(10)
, dmltype char(1) not null check(dmltype in (‘I’,’U’,’D’))
)
/

insert into plch_members values (1, ‘Adam’)
/
insert into plch_members values (2, ‘Brian’)
/
insert into plch_members values (3, ‘Chuck’)
/
insert into plch_members values (4, ‘David’)
/
insert into plch_members values (5, ‘Eric’)
/

insert into plch_members_stage values (6, ‘Frank’ , ‘I’)
/
insert into plch_members_stage values (3, ‘Charles’, ‘U’)
/
insert into plch_members_stage values (2, null , ‘D’)
/

commit
/
这个应用插入到临时表中的信息表明会员Frank需要被插入,Chuck需要改成Charles,而Brian需要被删除。

哪些选项包含了一个或者多个DML,可以在PLCH_MEMBERS表上执行(不出错)PLCH_MEMBERS_STAGE里面所指定的信息,使得下列这个测试查询会返回如下结果:
select id, name
from plch_members
order by id
/
ID NAME


     1 Adam
     3 Charles
     4 David
     5 Eric
     6 Frank

(A)
merge into plch_members m
using plch_members_stage s
on (m.id = s.id)
when matched then
when s.dmltype = ‘U’ then update set m.name = s.name
when s.dmltype = ‘D’ then delete m
when not matched then
insert (m.id, m.name)
values (s.id, s.name)
/
(B)
merge into plch_members m
using plch_members_stage s
on (m.id = s.id)
when matched then
update set m.name = s.name
delete where s.dmltype = ‘D’
when not matched then
insert (m.id, m.name)
values (s.id, s.name)
/
(C)
merge into plch_members m
using plch_members_stage s
on (m.id = s.id)
when matched then
update set m.name = s.name
where s.dmltype = ‘U’
delete where s.dmltype = ‘I’
when not matched then
insert (m.id, m.name)
values (s.id, s.name)
/

(D)
merge into plch_members m
using plch_members_stage s
on (m.id = s.id)
when matched then
update set m.name = nvl(s.name, ‘DUMMY’)
delete where s.dmltype = ‘D’
when not matched then
insert (m.id, m.name)
values (s.id, s.name)
/
(E)
merge into plch_members m
using plch_members_stage s
on (m.id = s.id)
when matched then
update set m.name = case s.dmltype
when ‘U’ then s.name
when ‘D’ then ‘DUMMY’
end
delete where s.dmltype = ‘D’
when not matched then
insert (m.id, m.name)
values (s.id, s.name)
/

(F)
insert into plch_members (id, name)
select id, name
from plch_members_stage
where dmltype = ‘I’
/
update (
select m.name oldname, s.name newname
from plch_members_stage s
join plch_members m
on m.id = s.id
where s.dmltype = ‘U’
)
set oldname = newname
/
delete plch_members
where id in (
select id
from plch_members_stage
where dmltype = ‘D’
)
/
A: 这不是正确的MERGE语法,你不能够在WHEN MATCHED之后执行一个WHEN … THEN UPDATE 或者 WHEN … THEN DELETE
这会报错:
ORA-00905: missing keyword.

B: 临时表中说到Brian必须被删除的那一行的NAME列是个NULL, 而DELETE WHERE 仅仅在 update发生之后才会执行,所以对Brian的修改失败了:
ORA-01407: cannot update (“SCOTT”.”PLCH_MEMBERS”.”NAME”) to NULL.

C: 这会插入Frank并且将Chuck改成Charles,并且输出”2 rows merged”——Brian不会被删除,因为DELETE WHERE 仅仅发生在被修改的行,而 UPDATE子句中的WHERE子句使得Brian不会被修改,因而也不会被删除。本选项执行之后我们会看到这个错误输出:
ID NAME


     1 Adam
     2 Brian
     3 Charles
     4 David
     5 Eric
     6 Frank

D: 通过在删除之前把Brian的名字改成DUMMY,这个选项是可行的,输出”3 rows merged”,随后的查询会显示所需的结果。
E: (推荐)
这个方法也可行,因为在删除之前Brian的名字被改成DUMMY,就如D选项。但是如果临时表输入的数据有错,使得dmltype=’I’并且名字为NULL, 则前一选项会插入一个名字为DUMMY的数据,而这个选项会报ORA-01407, 因此从处理错误数据的角度而言,本选项更为正确。

F:
独立执行三个DML语句:INSERT, UPDATE 和 DELETE,这同样可行,但是可能不如MERGE高效。也有可能 DMLTYPE=’D’ 的百分比很高,那么就对 MERGE 有太多的负面影响,因为要删除的行必须执行一个隐性的UPDATE。在这种情况下你必须测试,看看哪种方法最好。

4.相关参考网址
例题参考网址:
http://www.itpub.net/forum.php?mod=viewthread&tid=2054324&page=1#pid23281785

https://search.oracle.com/search/search

<think>好的,我现在需要回答用户关于OracleMERGE INTO语句的用法和示例的问题。首先,我需要回忆MERGE INTO的基本概念。MERGE INTO用于根据条件合并两个表的数据,可以同时处理更新和插入操作,这在数据仓库中很常见。 接下来,用户可能需要语法结构。我记得MERGE INTO的基本结构包括目标表、USING子句指定源数据,ON条件判断匹配,然后WHEN MATCHED和WHEN NOT MATCHED分别处理更新和插入。需要确认语法是否正确,比如是否需要分号,各部分的顺序。 然后,用户需要示例。我应该构造一个简单的例子,比如将员工奖金表的数据合并到总表中。假设有源表bonus和目标表employee,当员工ID匹配时更新奖金,不匹配时插入新记录。要写出具体的SQL语句,包括字段名和条件。 还要注意Oracle版本的区别,比如10g之后支持DELETE和条件操作。但用户可能只需要基础示例,所以先提供基本用法,再提到高级功能。 用户提供的引用中提到MySQL的替代方案是INSERT ... ON DUPLICATE KEY UPDATE,这可能对迁移有帮助,但用户的问题集中在Oracle,所以暂时不深入。 需要检查引用内容,引用1到4提到了语法、注意事项、迁移改造等,但用户需要的是用法和示例,所以重点在语法和示例部分,适当引用参考资料。 另外,用户可能关心性能、常见错误或最佳实践,但问题明确要求用法和示例,所以保持答案简洁,最后生成相关问题引导进一步学习。 最后,确保使用正确的中文术语,LaTeX格式的行内公式,如$table_name$,独立公式用$$...$$,但这里可能用不上。检查是否有语法错误,比如MERGE INTO的正确写法,字段列表的括号是否正确。</think>### Oracle MERGE INTO 语法及使用示例 #### 1. 基本语法 Oracle 的 `MERGE INTO` 语句用于将源表(或子查询)与目标表进行数据合并,根据匹配条件执行更新或插入操作。语法结构如下: ```sql MERGE INTO 目标表 别名 USING (源表/视图/子查询) 别名 ON (匹配条件) WHEN MATCHED THEN UPDATE SET 列1=值1, 列2=值2... [WHERE 条件] -- 10g及以上支持 [DELETE WHERE 条件] -- 10g及以上支持 WHEN NOT MATCHED THEN INSERT (列1, 列2...) VALUES (值1, 值2...) [WHERE 条件]; -- 10g及以上支持 ``` #### 2. 核心功能 - **更新匹配数据**:当 `ON` 条件满足时,执行 `UPDATE` 操作[^3] - **插入不匹配数据**:当 `ON` 条件不满足时,执行 `INSERT` 操作[^3] - **条件过滤**(10g+):可为 `UPDATE/INSERT` 添加额外条件[^3] - **删除操作**(10g+):可在匹配后通过 `DELETE WHERE` 删除数据[^3] #### 3. 使用示例 **场景**:将奖金表 `bonus` 的数据合并到员工表 `employees` 中,匹配时更新工资,不匹配时插入新记录。 ```sql MERGE INTO employees e USING ( SELECT employee_id, salary, bonus FROM bonus WHERE year = 2023 ) b ON (e.employee_id = b.employee_id) WHEN MATCHED THEN UPDATE SET e.salary = e.salary + b.bonus WHERE b.bonus > 1000 -- 仅当奖金超过1000时更新 WHEN NOT MATCHED THEN INSERT (employee_id, salary, hire_date) VALUES (b.employee_id, b.salary, SYSDATE); ``` #### 4. 注意事项 1. **锁机制**:执行时会锁定目标表,高并发场景需注意性能[^1] 2. **条件准确性**:`ON` 条件需唯一,否则可能重复操作[^1] 3. **日志与回滚**:建议开启日志以便故障恢复[^1] 4. **替代方案**:迁移到 MySQL 可使用 `INSERT ... ON DUPLICATE KEY UPDATE`[^4] #### 5. 版本差异 - **Oracle 9i/10g前**:仅支持基础更新/插入[^3] - **Oracle 10g+**:支持条件操作和删除[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值