我们操作数据库的时候,有时候会遇到insertOrUpdate这种需求。
如果数据库中存在数据就update,如果不存在就insert。
以前的时候,需要额外select查询一下,如果有数据就update,如果没有数据就insert。
而现在Orcale数据库都提供了 MERGE 方法来处理这种需求。
MERGE 命令使用一条语句从一个或者多个数据源中完成对表的更新和插入数据。
MERGE 语法:
MERGE INTO [your table-name] [rename your table here] USING ( [write your query here] )[rename your query-sql and using just like a table] ON ([conditional expression here] AND [...]...) WHEN MATCHED THEN [here you can execute some update sql or something else ] WHEN NOT MATCHED THEN [execute something else here ! ]
这里我们创建两张学生信息表,以此为例来进行说明:
-- Create table create table STUDENT_1 ( id VARCHAR2(64) not null, code VARCHAR2(30) not null, name VARCHAR2(100) not null, age NUMBER(3) not null, created_by VARCHAR2(64) not null, creation_date DATE not null, last_updated_by VARCHAR2(64) not null, last_update_date DATE not null, last_update_ip VARCHAR2(64) not null, version NUMBER(16) not null ) tablespace MES614 pctfree 10 initrans 1 maxtrans 255 storage ( initial 16 next 8 minextents 1 maxextents unlimited ); -- Add comments to the table comment on table STUDENT_1 is '1班学生信息表'; -- Add comments to the columns comment on column STUDENT_1.id is 'ID'; comment on column STUDENT_1.code is '学生证号'; comment on column STUDENT_1.name is '学生姓名'; comment on column STUDENT_1.age is '年龄'; comment on column STUDENT_1.created_by is '创建人'; comment on column STUDENT_1.creation_date is '创建日期'; comment on column STUDENT_1.last_updated_by is '最后更新人'; comment on column STUDENT_1.last_update_date is '最后更新时间'; comment on column STUDENT_1.last_update_ip is '最后更新IP'; comment on column STUDENT_1.version is '版本'; -- Create/Recreate primary, unique and foreign key constraints alter table STUDENT_1 add constraint PK_STUDENT_1 primary key (ID) using index tablespace MES614 pctfree 10 initrans 2 maxtrans 255 storage ( initial 64K next 1M minextents 1 maxextents unlimited );
学生信息表2除了和学生信息表1名称不一样之外,结构完全一致,所以这里就不在把学生信息表2(student_2)的建表语句放上来了。(Mes614是表空间名)
我们先手动的在student_2表中插入一些数据,然后先单独的写两个sql,分别将student_2中的数据插入或者更新到student_1中:
--将student_2中的数据插入到student_1中 insert into student_1 (id, code, name, age, created_by, creation_date, last_updated_by, last_update_date, last_update_ip, version) select t.id, t.code, t.name, t.age, t.created_by, t.creation_date, t.last_updated_by, t.last_update_date, t.last_update_ip, t.version from student_2 t --where ... --将student_1中数据除ID外随便乱改,然后通过merge into sql将其更新回来 merge into student_1 t using (select t1.id, t1.code, t1.name, t1.age from student_2 t1) me --这里可以只查出需要的字段 on (t.id = me.id) when matched then --当on()中条件成立时执行 update set t.code = me.code, t.name = me.name, t.age = me.age, t.version = t.version + 1;
下面我们就用merge into sql来同时进行插入和更新操作:
merge into student_1 t using (select t1.id, t1.code, t1.name, t1.age, t1.created_by, t1.creation_date, t1.last_updated_by, t1.last_update_date, t1.last_update_ip, t1.version from student_2 t1) me --这里可以只查出需要的字段 on (t.id = me.id) when matched then --当on()中条件成立时执行 update set t.code = me.code, t.name = me.name, t.age = me.age, t.version = t.version + 1 when not matched then --当on()中条件不成立时执行这部分 insert (id, code, name, age, created_by, creation_date, last_updated_by, last_update_date, last_update_ip, version) values (me.id, me.code, me.name, '22', me.created_by, me.creation_date, me.last_updated_by, me.last_update_date, me.last_update_ip, me.version);
注意事项:
Merge Into的原理是,从using 搜出来的结果逐条与on条件匹配,然后决定是update还是Insert。 当USING后面的sql没有查询到数据的时候,Merge Into语句是不会执行update和Insert操作的。
所以要想让Merge Into正常运行,要保证USING 后面的SELECT有数据。
转自:https://www.cnblogs.com/1012hq/p/11364698.html