Oracle合并数据操作(MERGE)

SQL标准于2003年增加了一个新的数据操作语句:MERGE(合并),它可以同时完成INSERT语句和UPDATE语句,甚至DELETE语句的操作。

标准合并语句

它的基本语法如下:

MERGE INTO target [AS t_alias]
USING source_table [AS s_alias]
ON (conditions)

WHEN MATCHED THEN
  UPDATE
  SET col1 = expr1,
      col2 = expr2,
      ...
      
WHEN NOT MATCHED THEN
  INSERT (col1, col2,...) 
  VALUES (expr1, expr2...);

其中,target_table是合并操作的目标表。

USING子句指定了数据源,可以是一个表或者查询语句。

ON子句指定了数据合并的条件,通常使用主键或者唯一键相等作为合并的条件。

对于数据源中的每条记录,如果目标表中存在匹配的记录,则执行WHEN MATCHED THEN分支的更新操作;如果目标表中不存在匹配的记录,则执行WHEN NOT MATCHED THEN分支的插入操作。

案例分析

案例使用的示例表

下面的操作会用到两个表,其中employee表中存储了员工的基本信息,包括姓名、入职日期、部门编号、薪资等字段。以下是该表中的部分数据:

emp_devp表是employee的备份表。

这两个表的初始化脚本可以在文章底部获取。
 

示例一

使用MERGE语句将employee表中dept_id为4的员工信息合并到emp_devp表中:

MERGE INTO emp_devp t
USING (SELECT emp_id, emp_name, sex, dept_id, manager,
              hire_date, job_id, salary, bonus, email
       FROM employee
       WHERE dept_id = 4) s
ON (t.emp_id = s.emp_id)

WHEN MATCHED THEN
  UPDATE
  SET t.emp_name = s.emp_name, 
      t.sex = s.sex, t.dept_id = s.dept_id, t.manager = s.manager,
      t.hire_date = s.hire_date, t.job_id = s.job_id, 
      t.salary = s.salary, t.bonus = s.bonus, t.email = s.email
      
WHEN NOT MATCHED THEN
  INSERT (emp_id, emp_name, sex, dept_id, manager,
          hire_date, job_id, salary, bonus, email) 
  VALUES (s.emp_id, s.emp_name, s.sex, s.dept_id, s.manager,
          s.hire_date, s.job_id, s.salary, s.bonus, s.email);

以上合并操作的判断条件为数据源和目标表中的emp_id是否相等。如果相等,则更新目标表中的数据;否则,插入数据到目标表。

第一次运行以上语句时,emp_devp表中没有任何数据,因此对于数据源中的每条记录都会执行WHEN NOT MATCHED THEN分支,也就是插入数据。


以上语句执行成功之后,我们可以查看合并后的数据:

示例二

MERGE语句还支持DELETE子句,可以用于删除目标表中匹配的数据,例如:

MERGE INTO emp_devp t
USING (SELECT emp_id, emp_name, sex, dept_id, manager,
              hire_date, job_id, salary, bonus, email
       FROM employee
       WHERE dept_id = 4) s
ON (t.emp_id = s.emp_id)

WHEN MATCHED THEN
  UPDATE
  SET t.emp_name = s.emp_name, 
      t.sex = s.sex, t.dept_id = s.dept_id, t.manager = s.manager,
      t.hire_date = s.hire_date, t.job_id = s.job_id, 
      t.salary = s.salary, t.bonus = s.bonus, t.email = s.email
      
  DELETE WHERE t.emp_name = '赵氏'
      
WHEN NOT MATCHED THEN
  INSERT (emp_id, emp_name, sex, dept_id, manager,
          hire_date, job_id, salary, bonus, email) 
  VALUES (s.emp_id, s.emp_name, s.sex, s.dept_id, s.manager,
          s.hire_date, s.job_id, s.salary, s.bonus, s.email);

我们在WHEN MATCHED THEN分支中增加了一个DELETE子句和一个WHERE条件。

如果运行以上语句,emp_devp表中姓名为“赵氏”的员工记录将会被删除。

 通过查询,发现emp_name为“赵氏”的记录被删除了。

示例表和脚本

--员工信息表
CREATE TABLE employee
    ( emp_id    NUMBER
    , emp_name  VARCHAR2(50) NOT NULL
    , sex       VARCHAR2(10) NOT NULL
    , dept_id   INTEGER NOT NULL
    , manager   INTEGER
    , hire_date DATE NOT NULL
    , job_id    INTEGER NOT NULL
    , salary    NUMERIC(8,2) NOT NULL
    , bonus     NUMERIC(8,2)
    , email     VARCHAR2(100) NOT NULL
  , comments  VARCHAR2(500)
  , create_by VARCHAR2(50) NOT NULL
  , create_ts TIMESTAMP NOT NULL
  , update_by VARCHAR2(50) 
  , update_ts TIMESTAMP
    ) ;
COMMENT ON TABLE employee IS '员工信息表';
COMMENT ON COLUMN employee.emp_id IS '员工编号,自增主键';
COMMENT ON COLUMN employee.emp_name IS '员工姓名';
COMMENT ON COLUMN employee.sex IS '性别';
COMMENT ON COLUMN employee.dept_id IS '部门编号';
COMMENT ON COLUMN employee.manager IS '上级经理';
COMMENT ON COLUMN employee.hire_date IS '入职日期';
COMMENT ON COLUMN employee.job_id IS '职位编号';
COMMENT ON COLUMN employee.salary IS '月薪';
COMMENT ON COLUMN employee.bonus IS '年终奖金';
COMMENT ON COLUMN employee.email IS '电子邮箱';
COMMENT ON COLUMN employee.comments IS '备注信息';
COMMENT ON COLUMN employee.create_by IS '创建者';
COMMENT ON COLUMN employee.create_ts IS '创建时间';
COMMENT ON COLUMN employee.update_by IS '修改者';
COMMENT ON COLUMN employee.update_ts IS '修改时间';
 
 
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (1,'刘备', '男', 1, NULL, DATE '2000-01-01', 1, 30000, 10000, '[email protected]', NULL, 'Admin', TIMESTAMP '2000-01-01 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (2,'关羽', '男', 1, 1, DATE '2000-01-01', 2, 26000, 10000, '[email protected]', NULL, 'Admin', TIMESTAMP '2000-01-01 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (3,'张飞', '男', 1, 1, DATE '2000-01-01', 2, 24000, 10000, '[email protected]', NULL, 'Admin', TIMESTAMP '2000-01-01 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (4,'诸葛亮', '男', 2, 1, DATE '2006-03-15', 3, 24000, 8000, '[email protected]', NULL, 'Admin', TIMESTAMP '2006-03-15 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (5,'黄忠', '男', 2, 4, DATE '2008-10-25', 4, 8000, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2008-10-25 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (6,'魏延', '男', 2, 4, DATE '2007-04-01', 4, 7500, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2007-04-01 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (7,'孙尚香', '女', 3, 1, DATE '2002-08-08', 5, 12000, 5000, '[email protected]', NULL, 'Admin', TIMESTAMP '2002-08-08 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (8,'孙丫鬟', '女', 3, 7, DATE '2002-08-08', 6, 6000, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2002-08-08 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (9,'赵云', '男', 4, 1, DATE '2005-12-19', 7, 15000, 6000, '[email protected]', NULL, 'Admin', TIMESTAMP '2005-12-19 10:00:00', 'Admin', TIMESTAMP '2006-12-31 10:00:00');
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (10,'廖化', '男', 4, 9, DATE '2009-02-17', 8, 6500, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2009-02-17 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (11,'关平', '男', 4, 9, DATE '2011-07-24', 8, 6800, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2011-07-24 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (12,'赵氏', '女', 4, 9, DATE '2011-11-10', 8, 6600, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2011-11-10 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (13,'关兴', '男', 4, 9, DATE '2011-07-30', 8, 7000, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2011-07-30 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (14,'张苞', '男', 4, 9, DATE '2012-05-31', 8, 6500, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2012-05-31 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (15,'赵统', '男', 4, 9, DATE '2012-05-03', 8, 6000, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2012-05-03 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (16,'周仓', '男', 4, 9, DATE '2010-02-20', 8, 8000, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2010-02-20 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (17,'马岱', '男', 4, 9, DATE '2014-09-16', 8, 5800, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2014-09-16 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (18,'法正', '男', 5, 2, DATE '2017-04-09', 9, 10000, 5000, '[email protected]', NULL, 'Admin', TIMESTAMP '2017-04-09 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (19,'庞统', '男', 5, 18, DATE '2017-06-06', 10, 4100, 2000, '[email protected]', NULL, 'Admin', TIMESTAMP '2017-06-06 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (20,'蒋琬', '男', 5, 18, DATE '2018-01-28', 10, 4000, 1500, '[email protected]', NULL, 'Admin', TIMESTAMP '2018-01-28 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (21,'黄权', '男', 5, 18, DATE '2018-03-14', 10, 4200, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2018-03-14 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (22,'糜竺', '男', 5, 18, DATE '2018-03-27', 10, 4300, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2018-03-27 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (23,'邓芝', '男', 5, 18, DATE '2018-11-11', 10, 4000, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2018-11-11 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (24,'简雍', '男', 5, 18, DATE '2019-05-11', 10, 4800, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2019-05-11 10:00:00', NULL, NULL);
INSERT INTO employee(EMP_ID,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) VALUES (25,'孙乾', '男', 5, 18, DATE '2018-10-09', 10, 4700, NULL, '[email protected]', NULL, 'Admin', TIMESTAMP '2018-10-09 10:00:00', NULL, NULL);




--员工信息表备份表
CREATE TABLE emp_devp
    ( emp_id    NUMBER
    , emp_name  VARCHAR2(50) NOT NULL
    , sex       VARCHAR2(10) NOT NULL
    , dept_id   INTEGER NOT NULL
    , manager   INTEGER
    , hire_date DATE NOT NULL
    , job_id    INTEGER NOT NULL
    , salary    NUMERIC(8,2) NOT NULL
    , bonus     NUMERIC(8,2)
    , email     VARCHAR2(100) NOT NULL
    ) ;
COMMENT ON TABLE emp_devp IS '员工信息表备份表';
COMMENT ON COLUMN emp_devp.emp_id IS '员工编号,自增主键';
COMMENT ON COLUMN emp_devp.emp_name IS '员工姓名';
COMMENT ON COLUMN emp_devp.sex IS '性别';
COMMENT ON COLUMN emp_devp.dept_id IS '部门编号';
COMMENT ON COLUMN emp_devp.manager IS '上级经理';
COMMENT ON COLUMN emp_devp.hire_date IS '入职日期';
COMMENT ON COLUMN emp_devp.job_id IS '职位编号';
COMMENT ON COLUMN emp_devp.salary IS '月薪';
COMMENT ON COLUMN emp_devp.bonus IS '年终奖金';
COMMENT ON COLUMN emp_devp.email IS '电子邮箱';

猜你喜欢

转载自blog.csdn.net/liangmengbk/article/details/124269132