我们操作数据库的时候,有时候会遇到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