DB2 Merge 语句的作用非常强大,它可以将一个表中的数据合并到另一个表中,在合并的同时可以进行插入、删除、更新等操作。我们还是先来看个简单的例子吧,假设你定义了一个雇员表(employe),一个经理表(manager),如下所示:

关键字、参数

into子句

在into子句中指定所要修改或者插入数据的目标表

using子句

在using子句中指定用来修改或者插入的数据源。数据源可以是表、视图或者一个子查询语句。

on子句

在on子句中指定执行插入或者修改的满足条件。

when matched | not matched

用该子句通知数据库如何对满足或不满足条件的结果做出相应的操作。可以使用以下的两类子句。

merge_update子句

merge_update子句执行对目标表中的字段值修改。当在符合on子句条件的情况下执行。如果修改子句执行,则目标表上的修改触发器将被触发。

限制:当修改一个视图时,不能指定一个default值

merge_insert 子句

merge_insert子句执行当不符合on子句条件时,往目标表中插入数据。如果插入子句执行,则目标表上插入触发器将被触发。

限制:当修改一个视图时,不能指定一个default值
 
  1. ---雇员表(EMPLOYE)
  2. CREATE TABLE EMPLOYE (
  3. EMPLOYEID INTEGER  NOT NULL,---员工号
  4. NAME VARCHAR(20) NOT NULL,---姓名
  5. SALARY DOUBLE---薪水
  6. );
  7. INSERT INTO EMPLOYE (EMPLOYEID,NAME,SALARY) VALUES
  8. (1,'张三',1000),
  9. (2,'李四',2000),
  10. (3,'王五',3000),
  11. (4,'赵六',4000),
  12. (5,'高七',5000);
  13. --经理表(MANAGER)
  14. CREATE TABLE MANAGER (
  15. EMPLOYEID INTEGER  NOT NULL,---经理号
  16. NAME VARCHAR(20) NOT NULL,---姓名
  17. SALARY DOUBLE---薪水
  18. );
  19. INSERT INTO MANAGER (MANAGERID,NAME,SALARY) VALUES
  20. (3,'王五',5000),
  21. (4,'赵六',6000);

经过一段时间,你发现这样的数据模型,或者说表结构设计简直就是一大败笔,经理和雇员都是员工嘛,为什么要设计两个表呢?发现错误后就需要改正,所以你决定,删除经理表(MANAGER)表,将MANAGER 表中的数据合并到EMPLOYE 表中,仔细分析发现,王五在两个表中都存在(可能是干的好升官了),而刘八在EMPLOYE 表中并不存在,现在,我们要求把EMPLOYE 表中不存在的MANAGER都插入到EMPLOYE 表中,存在的更新薪水。该怎么办呢?这个问题并不难,通常,我们可以分两步,如下所示:

  1. --更新存在的
  2. UPDATE EMPLOYE AS EM SET SALARY=(SELECT SALARY FROM MANAGER WHERE MANAGERID=EM.EMPLOYEID)
  3. WHERE EMPLOYEID IN (
  4. SELECT MANAGERID FROM MANAGER
  5. );
  6. ---插入不存在的
  7. INSERT INTO EMPLOYE (EMPLOYEID,NAME,SALARY)
  8. SELECT MANAGERID,NAME,SALARY FROM MANAGER WHERE MANAGERID NOT IN (
  9. SELECT EMPLOYEID FROM EMPLOYE
  10. );

上面的处理是可以的,但是我们还可以有更简单的方法,就是用Merge语句,如下所示:

  1. MERGE INTO EMPLOYE AS EM
  2. USING MANAGER AS MA
  3. ON EM.EMPLOYEID=MA.MANAGERID
  4. WHEN MATCHED THEN UPDATE SET EM.SALARY=MA.SALARY
  5. WHEN NOT MATCHED THEN INSERT VALUES (MA.MANAGERID,MA.NAME,MA.SALARY);

在上面的处理中,我们用经理表(MANAGER)的薪水更新了雇员表(EMPLOYE)的薪水,假设现在要求,如果经理表(MANAGER)的薪水>雇员表(EMPLOYE)的薪水的时候更新,否则不更新,怎么办呢?如下:

  1. MERGE INTO EMPLOYE AS EM
  2. USING MANAGER AS MA
  3. ON EM.EMPLOYEID=MA.MANAGERID
  4. WHEN MATCHED AND EM.SALARY<MA.SALARY THEN UPDATE SET EM.SALARY=MA.SALARY
  5. WHEN NOT MATCHED THEN INSERT VALUES (MA.MANAGERID,MA.NAME,MA.SALARY)
  6. ELSE IGNORE;

不仔细的朋友可能没有看出上面两条语句的区别,哈哈,请仔细对比一下这两条语句。上面的语句中多了ELSE IGNORE语句,它的意思正如它英文的意思,其它情况忽略不处理。如果你认为理论上应该不存在EM.SALARY>MA.SALARY的数据,如果有,说明有问题,你想抛个异常,怎么办?如下:

  1. MERGE INTO EMPLOYE AS EM
  2. USING MANAGER AS MA
  3. ON EM.EMPLOYEID=MA.MANAGERID
  4. WHEN MATCHED AND EM.SALARY<MA.SALARY THEN UPDATE SET EM.SALARY=MA.SALARY
  5. WHEN MATCHED AND EM.SALARY>MA.SALARY THEN SIGNAL SQLSTATE '70001' SET MESSAGE_TEXT = 'EM.SALARY>MA.SALARY'
  6. WHEN NOT MATCHED THEN INSERT VALUES (MA.MANAGERID,MA.NAME,MA.SALARY)
  7. ELSE IGNORE;

对于EM.SALARY>MA.SALARY的情况,如果你不想抛异常,而是删除EMPLOYE中的数据,怎么办?如下:

  1. MERGE INTO EMPLOYE AS EM
  2. USING MANAGER AS MA
  3. ON EM.EMPLOYEID=MA.MANAGERID
  4. WHEN MATCHED AND EM.SALARY<MA.SALARY THEN UPDATE SET EM.SALARY=MA.SALARY
  5. WHEN MATCHED AND EM.SALARY>MA.SALARY THEN DELETE
  6. WHEN NOT MATCHED THEN INSERT VALUES (MA.MANAGERID,MA.NAME,MA.SALARY)
  7. ELSE IGNORE;

update

多表联查更新多字段,需要最后增加where条件来限制更新内容。

表结构:
CREATE TABLE ATEST
 (ID    INTEGER,
  NAME  VARCHAR(256),
  CODE  INTEGER,
  NAME2 VARCHAR(256)
 )

CREATE TABLE BTEST
 (ID    INTEGER,
  CODE  INTEGER
 )

CREATE TABLE CTEST
 (ID    INTEGER,
  NAME  VARCHAR(256),
  NAME2 VARCHAR(256)
 )

SQL语句:
一张表更新另一张表的字段:
update atest
set atest.name=(select ctest.name from ctest where atest.id = ctest.id)
where atest.id in  (select ctest.id from ctest);

两张表关联更新另一张表的字段:
update atest
set (name,name2) = (SELECT CASE WHEN CTEST.NAME IS NULL THEN ATEST.NAME ELSE CTEST.NAME END, CASE WHEN CTEST.NAME2 IS NULL THEN ATEST.NAME2 ELSE CTEST.NAME2 END FROM BTEST LEFT JOIN CTEST on BTEST.ID = CTEST.ID  WHERE atest.CODE = BTEST.CODE)
WHERE atest.CODE IN (SELECT BTEST.CODE FROM BTEST);

另外一个: http://blog.csdn.net/Bobwu/archive/2009/01/13/3768636.aspx1.
declare
cursor t1 is select * from tablename;
begin
for rec in t1 loop
update tablename t set t.detail=rec.jieshao where t.objectid=rec.objid;
end loop;
end;

2.

update   student   set   (name,id   )=   
  (select   name   ,id     from   (select   student.rowid   rd,student1.name,student1.id   from   student1,student   where   student1.int_id   =student.int_id)   tmp   
  where   student.rowid=tmp.rd);   
  commit;

3.

update test_a a set (a.name,a.age)=
(select b.name,b.age from test_b b where a.id = b.id) where exists
(select * from test_b c where c.id=a.id)

4.

UPDATE   t_A   SET   Djrq=     
  (   
          SELECT   djrq   FROM   t_B   WHERE   t_A.ID   =   T_B.ID     
          WHERE   ROWNUM   =   1     
  )   
  WHERE   t_A.ID   IN     
  (   
          SELECT   ID   FROM   t_B   WHERE   jwh='XX村'   
  )

5.

update tbl1 a
   set (a.col1, a.col2) = (select b.col1, b.col2
                              from tbl2 b
                              where a.key = b.key)
   where a.key in(select key from tbl2)

05-07 15:23