▌merge into 用法
使用merge命令可以通过一个SQL语句对一个表同时执行insert和update。
--merge into语法:
MERGE INTO target - table A
USING source - table sql B
ON (conditional expression and .. . .. .)
WHEN MATCHED THEN
UPDATE set A.更新字段 = B.字段
WHEN NOT MATCHED THEN
INSERT values (B.值1, B.值2……)
语法解析:
判断A表和B表是否满足ON中的条件,如果满足则用(USINE)B表数据更新(UPDATE)A表;如果不满足,则将B表数据插入(INSERT)到A表。
可以理解成A表为目标表,B表为数据源表。
源表B可能是一张表结构不同于a的表,有可能是一张构建相同表结构的临时表,也有可能是使用dual来实现数据数据.
MATCHED: 匹配。
--测试数据:构造临时表
drop table scott.emp_temp;
create table scott.emp_temp as select * from scott.emp ;
drop table scott.dept_temp;
create table scott.dept_temp as select * from scott.dept;
--查看结果
select * from scott.emp_temp;
select * from scott.dept_temp;
/*
要求:给所有部门的基本工资初始化为5000
提示:使用alter给表添加salary字段;
使用marge实现
功能点:在ON条件中使用常量过滤谓词
*/
alter table scott.dept_temp add salary number(7,2) ;
merge into scott.dept_temp a
using (select '5000' sal from dual) b
on (1 = 1)
when matched then
update set a.salary = b.sal;
--查看结果
select * from scott.dept_temp;
/**
要求:通过临时表更新目标表数据,无则新增
*/
--测试数据
insert into scott.emp_temp
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
values
('1', '技术大本营', 'IT', '', SYSDATE, '5000', 500, 10);
---使用 MERGE 命令可通过单个命令同时执行 INSERT 和 UPDATE
MERGE INTO scott.emp a
USING (Select EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO
FROM scott.emp_temp) b
ON (a.empno = b.empno)
WHEN MATCHED THEN
UPDATE SET a.sal = b.sal
WHEN NOT MATCHED THEN
insert
values
(b.EMPNO, b.ENAME, b.JOB, b.MGR, b.HIREDATE, b.SAL, b.COMM, b.DEPTNO);
--查看结果
select * from scott.emp;

--错误提示ORA-30926: 无法在源表中获得一组稳定的行:
原因:目标表有重复的数据,导致merge(合并)的时候,无法确定是合并哪一条记录,导致出现无法获取稳定的行。
解决方法:目标表做唯一约束保护数据。USING后面的集合必须不含重复,如果有就先去除。
即关联的ON条件确保唯一,对目标表做一个主键约束。
--创建唯一约束脚本
-- Create/Recreate primary, unique and foreign key constraints
alter table SCOTT.EMP
add constraint PK_EMP primary key (EMPNO)
using index
tablespace USERS
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 64K
next 1M
minextents 1
maxextents unlimited
);
Oracle在9i引入了merge命令;
Oracle 10g merge命令有如下一些改进:
1、UPDATE或INSERT子句是可选的;
2、UPDATE和INSERT子句可以加WHERE子句;
3、在ON条件中使用常量过滤谓词(例如 on(1=0),即无条件的将数据插入目标表)来insert所有的行到目标表中,不需要连接源表和目标表;
4、UPDATE子句后面可以跟DELETE子句来去除一些不需要的行。
--使用Merge的好处:
业务逻辑上避免了更新与新增分开判断,提高性能,尤其是在大数据或批量处理数据。
需要注意的地方:
1、从语法条件上看(ON (join condition)),merge into也是一个危险的语法。如果不慎重使用,会将源表全部覆盖到目标表,既危险又浪费效率,违背了增量同步的原则。所以在设计表结构时,一般每条记录都有“更新时间”的字段,用目标表“最大更新时间”判断源表数据是否有更新和新增的信息。
2、更新的字段,不允许有关联条件的字段(join condition)。比如条件是 A.ID=B.ID,那么使用“SET A.ID=B.ID”将报出一个莫名其妙的提示错误,例如错误提示“ORA-38104: 无法更新 ON 子句中引用的列: "A"."ID".
=====================================
说明:DELETE语句删除的是满足matched关联on条件,同时也要是update更新内容的子集,否则不会删除任何内容。


============================
2019,未来可期




merge into | 实现同时执行insert和update
