ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 使用merge 需要注意的问题

使用merge 需要注意的问题

原创 Linux操作系统 作者:pingley 时间:2012-05-11 22:49:28 0 删除 编辑
使用merge 需要注意的问题
场景一:
先创建两张测试用的表。
SQL> create table merge_01 as select employee_id,first_name,last_name,salary
  2  from hr.employees
  3  /
Table created.
SQL> create table merge_02 as select employee_id,first_name,last_name,salary
  2  from hr.employees
  3  where employee_id < 170;
Table created.
通过employee_id 列来匹配,如果匹配到,则update 目标表的salary 列,如果没有匹配到,则insert 源表中的记录。这种场景下merge 语句可以正确的完成我们的需求。
SQL> edit
Wrote file afiedt.buf
  1  merge into merge_02
  2  using merge_01
  3  on (merge_02.employee_id = merge_01.employee_id)
  4  when matched then
  5  update set merge_02.salary = merge_02.salary * 1.1
  6  when not matched then
  7* insert values(merge_01.employee_id,merge_01.first_name,merge_01.last_name,merge_01.salary)
SQL> /
107 rows merged.
SQL> rollback;
Rollback complete.
场景二:
上面的语句可以正常的执行,把merge 语句所做的修改rollback掉,换一个场景进行测试。往merge_01 表中插入重复的数据,使得其中的每一条记录都存在一个副本。
SQL> insert into merge_01 select employee_id,first_name,last_name,salary
  2  from hr.employees;
107 rows created.
SQL> select count(*) from merge_01
  2  where employee_id = 100;
  COUNT(*)
----------
         2
再使用上面的merge 语句来操作merge_01,merge_02 表。出现ORA-30926 的错误,因为在源表merge_01 中存在两条记录匹配目标表merge_02 中的每一条记录。这情况下可以考虑添加主键约束来解决,使得源表中的记录不重复。
SQL> edit
Wrote file afiedt.buf
  1  merge into merge_02
  2  using merge_01
  3  on (merge_02.employee_id = merge_01.employee_id)
  4  when matched then
  5  update set merge_02.salary = merge_02.salary * 1.1
  6  when not matched then
  7* insert values(merge_01.employee_id,merge_01.first_name,merge_01.last_name,merge_01.salary
SQL> /
merge into merge_02
           *
ERROR at line 1:
ORA-30926: 无法在源表中获得一组稳定的行
如果把目标表truncate 掉,这样源表merge_01 就不存在多条记录,匹配目标表中的每条记录了。这时候下面的merge 语句可以“正常”的执行,但是不一定是正确的执行,因为这可能是你不想要的结果,这一点需要注意。在这种情况下,相当于
insert into merge_02 select * from merge_01;
SQL> truncate table merge_02;
Table truncated.
SQL>  merge into merge_02
  2   using merge_01
  3   on (merge_02.employee_id = merge_01.employee_id)
  4   when matched then
  5   update set merge_02.salary = merge_02.salary * 1.1
  6   when not matched then
  7   insert values(merge_01.employee_id,merge_01.first_name,merge_01.last_name,merge_01.salary)
  8  /
SQL> select * from merge_02
  2  where employee_id = 100;
EMPLOYEE_ID FIRST_NAME       LAST_NAME            SALARY
----------- ---------------- ---------------- ----------
        100 Steven           King                  24000
        100 Steven           King                  24000
场景三:
 如果merge 语句中的目标表中存在多条记录匹配源表中的记录会是怎么样?下面我们来测试一下。
SQL> truncate table merge_01;
Table truncated.
SQL> insert into merge_01 select employee_id,first_name,last_name,salary
  2  from hr.employees;
107 rows created.
SQL> commit;
Commit complete.
现在在merge_02 中存在多条记录匹配merge_01 中的每一条记录,再来执行下面的merge 语句。下面查询下employee_id = 100 的用户的salary。
SQL> select * from merge_02
  2  where employee_id = 100;
EMPLOYEE_ID FIRST_NAME       LAST_NAME            SALARY
----------- ---------------- ---------------- ----------
        100 Steven           King                  24000
        100 Steven           King                  24000
SQL>  merge into merge_02
  2   using merge_01
  3   on (merge_02.employee_id = merge_01.employee_id)
  4   when matched then
  5   update set merge_02.salary = merge_02.salary * 1.1
  6   when not matched then
  7   insert values(merge_01.employee_id,merge_01.first_name,merge_01.last_name,merge_01.salary)
  8  /
214 rows merged.
目标表中在源表中匹配到的每一条记录都会被更新,在中场景下merge 虽然也是"正常"执行的,但是却并一定正确,这一点需要注意。
SQL> select * from merge_02
  2  where employee_id = 100;
EMPLOYEE_ID FIRST_NAME       LAST_NAME            SALARY
----------- ---------------- ---------------- ----------
        100 Steven           King                  26400
        100 Steven           King                  26400
小结:merge 语句的“正常”执行,不一定意味着正确。使用merge 语句前需要对源表和目标表中的数据的状态有所了解。以便确定merge 语句做了正确的事情。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26110315/viewspace-723389/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2012-02-06

  • 博文量
    169
  • 访问量
    715392