现在的位置: 首页 > 综合 > 正文

Oracle的MERGE语句

2013年03月23日 ⁄ 综合 ⁄ 共 6041字 ⁄ 字号 评论关闭
MERGE语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句。
通过MERGE语句,根据一张表或子查询的连接条件对另外一张表进行查询,
连接条件匹配上的进行UPDATE,无法匹配的执行INSERT。
这个语法仅需要一次全表扫描就完成了全部工作,执行效率要高于INSERT+UPDATE。

/*語法:
MERGE [INTO [schema .] table [t_alias]
USING [schema .] { table | view | subquery } [t_alias]
ON ( condition )
WHEN MATCHED THEN merge_update_clause
WHEN NOT MATCHED THEN merge_insert_clause;
*/

--全部男生记录
create table fzq1 as select * from fzq where sex=1;
--全部女生记录
create table fzq2 as select * from fzq where sex=0;
/*涉及到两个表关联的例子*/
--更新表fzq1使得id相同的记录中chengji字段+1,并且更新name字段。
--如果id不相同,则插入到表fzq1中.
--将fzq1表中男生记录的成绩+1,女生插入到表fzq1中

merge into fzq1 aa --fzq1表是需要更新的表
  using fzq bb -- 关联表
  on (aa.id=bb.id) --关联条件
when matched then --匹配关联条件,作更新处理
  update set
    aa.chengji=bb.chengji+1,
    aa.name=bb.name --此处只是说明可以同时更新多个字段。
when not matched then --不匹配关联条件,作插入处理。如果只是作更新,下面的语句可以省略。
    insert values( bb.id, bb.name, bb.sex,bb.kecheng,bb.chengji);
/*涉及到多个表关联的例子,我们以三个表为例,只是作更新处理,不做插入处理。当然也可以只做插入处理*/
--将fzq1表中女生记录的成绩+1,没有直接去sex字段。而是fzq和fzq2关联。
merge into fzq1 aa --fzq1表是需要更新的表
  using (select fzq.id,fzq.chengji from fzq join fzq2
    on fzq.id=fzq2.id) bb -- 数据集
  on (aa.id=bb.id) --关联条件
when matched then --匹配关联条件,作更新处理
  update set aa.chengji=bb.chengji+1

/*不能做的事情*/

merge into fzq1 aa using fzq bb on (aa.id=bb.id) 
when matched then 
  update set aa.id=bb.id+1;

/*系统提示:
ORA-38104: Columns referenced in the ON Clause cannot be updated: "AA"."ID"
我们不能更新on (aa.id=bb.id)关联条件中的字段*/

update fzq1 set id=(select id+1 from fzq where fzq.id=fzq1.id)
where id in (select id from fzq);

from this:http://hi.baidu.com/rhuang666/blog/item/09bae812ce7a752add540120.html

Oracle9i引入了MERGE命令,你能够在一个SQL语句中对一个表同时执行inserts和updates操作. MERGE命令从一个或多个数据源中选择行来updating或inserting到一个或多个表.

Oracle 10g中MERGE有如下一些改进:
1、UPDATE或INSERT子句是可选的
2、UPDATE和INSERT子句可以加WHERE子句
3、ON条件中使用常量过滤谓词来insert所有的行到目标表中,不需要连接源表和目标表
4、UPDATE子句后面可以跟DELETE子句来去除一些不需要的行

首先创建示例表:

create table PRODUCTS
(
PRODUCT_ID INTEGER,
PRODUCT_NAME VARCHAR2(60),
CATEGORY VARCHAR2(60)
);

insert into PRODUCTS values (1501, 'VIVITAR 35MM', 'ELECTRNCS');
insert into PRODUCTS values (1502, 'OLYMPUS IS50', 'ELECTRNCS');
insert into PRODUCTS values (1600, 'PLAY GYM', 'TOYS');
insert into PRODUCTS values (1601, 'LAMAZE', 'TOYS');
insert into PRODUCTS values (1666, 'HARRY POTTER', 'DVD');
commit;

create table NEWPRODUCTS
(
PRODUCT_ID INTEGER,
PRODUCT_NAME VARCHAR2(60),
CATEGORY VARCHAR2(60)
);

insert into NEWPRODUCTS values (1502, 'OLYMPUS CAMERA', 'ELECTRNCS');
insert into NEWPRODUCTS values (1601, 'LAMAZE', 'TOYS');
insert into NEWPRODUCTS values (1666, 'HARRY POTTER', 'TOYS');
insert into NEWPRODUCTS values (1700, 'WAIT INTERFACE', 'BOOKS');
commit;


1、可省略的UPDATE或INSERT子句

Oracle 9i, MERGE语句要求你必须同时指定INSERT和UPDATE子句.
而在Oracle 10g, 你可以省略UPDATE或INSERT子句中的一个.
下面的例子根据表NEWPRODUCTS的PRODUCT_ID字段是否匹配来updates表PRODUCTS的信息:

SQL> MERGE INTO products p
2 USING newproducts np
3 ON (p.product_id = np.product_id)
4 WHEN MATCHED THEN
5 UPDATE
6 SET p.product_name = np.product_name,
7 p.category = np.category;

3 rows merged.

SQL> SELECT * FROM products;

PRODUCT_ID PRODUCT_NAME CATEGORY
---------- -------------------- ----------
1501 VIVITAR 35MM ELECTRNCS
1502 OLYMPUS CAMERA ELECTRNCS
1600 PLAY GYM TOYS
1601 LAMAZE TOYS
1666 HARRY POTTER TOYS
SQL>
SQL> ROLLBACK;
Rollback complete.
SQL>

下面例子省略UPDATE子句, 把表NEWPRODUCTS中新的PRODUCT_ID插入到表PRODUCTS中,
对于在两个表中能够匹配上PRODUCT_ID的数据不作任何处理.
从这个例子你能看到PRODUCT_ID=1700的行被插入到表PRODUCTS中.

SQL> MERGE INTO products p
2 USING newproducts np
3 ON (p.product_id = np.product_id)
4 WHEN NOT MATCHED THEN
5 INSERT
6 VALUES (np.product_id, np.product_name,
7 np.category);

1 row merged.

SQL> SELECT * FROM products;

PRODUCT_ID PRODUCT_NAME CATEGORY
---------- -------------------- ----------
1501 VIVITAR 35MM ELECTRNCS
1502 OLYMPUS IS50 ELECTRNCS
1600 PLAY GYM TOYS
1601 LAMAZE TOYS
1666 HARRY POTTER DVD
1700 WAIT INTERFACE BOOKS

2、带条件的Updates和Inserts子句

你能够添加WHERE子句到UPDATE或INSERT子句中去, 来跳过update或insert操作对某些行的处理.
下面例子根据表NEWPRODUCTS来更新表PRODUCTS数据, 但必须字段CATEGORY也得同时匹配上,
在这个例子中, 产品ID为1502,1601和1666匹配ON条件但是1666的category不匹配.
因此MERGE命令只更新两行数据.

SQL> MERGE INTO products p
2 USING newproducts np
3 ON (p.product_id = np.product_id)
4 WHEN MATCHED THEN
5 UPDATE
6 SET p.product_name = np.product_name
7 WHERE p.category = np.category;

2 rows merged.

SQL> SELECT * FROM products;

PRODUCT_ID PRODUCT_NAME CATEGORY
---------- -------------------- ----------
1501 VIVITAR 35MM ELECTRNCS
1502 OLYMPUS CAMERA ELECTRNCS
1600 PLAY GYM TOYS
1601 LAMAZE TOYS
1666 HARRY POTTER DVD
SQL>
SQL> rollback;

下面例子展示了在Updates和Inserts子句都使用WHERE子句:

SQL> MERGE INTO products p
2 USING newproducts np
3 ON (p.product_id = np.product_id)
4 WHEN MATCHED THEN
5 UPDATE
6 SET p.product_name = np.product_name,
7 p.category = np.category
8 WHERE p.category = 'DVD'
9 WHEN NOT MATCHED THEN
10 INSERT
11 VALUES (np.product_id, np.product_name, np.category)
12 WHERE np.category != 'BOOKS'
SQL> /

1 row merged.

SQL> SELECT * FROM products;

PRODUCT_ID PRODUCT_NAME CATEGORY
---------- -------------------- ----------
1501 VIVITAR 35MM ELECTRNCS
1502 OLYMPUS IS50 ELECTRNCS
1600 PLAY GYM TOYS
1601 LAMAZE TOYS
1666 HARRY POTTER TOYS

SQL>rollback;

3、无条件的Inserts

你能够不用连接源表和目标表就把源表的数据插入到目标表中.
这对于你想插入所有行到目标表时是非常有用的.
Oracle 10g现在支持在ON条件中使用常量过滤谓词. 举个常量过滤谓词例子ON (1=0).
下面例子从源表插入行到表PRODUCTS, 不检查这些行是否在表PRODUCTS中存在:

SQL> MERGE INTO products p
2 USING newproducts np
3 ON (1=0)
4 WHEN NOT MATCHED THEN
5 INSERT
6 VALUES (np.product_id, np.product_name, np.category)
7 WHERE np.category = 'BOOKS'
SQL> /

1 row merged.

SQL> SELECT * FROM products;

PRODUCT_ID PRODUCT_NAME CATEGORY
---------- -------------------- ----------
1501 VIVITAR 35MM ELECTRNCS
1502 OLYMPUS IS50 ELECTRNCS
1600 PLAY GYM TOYS
1601 LAMAZE TOYS
1666 HARRY POTTER DVD
1700 WAIT INTERFACE BOOKS
6 rows selected.
SQL>rollback;

4、新增加的DELETE子句
Oracle 10g中的MERGE提供了在执行数据操作时清除行的选项.
你能够在WHEN MATCHED THEN UPDATE子句中包含DELETE子句.
DELETE子句必须有一个WHERE条件来删除匹配某些条件的行.
匹配DELETE WHERE条件但不匹配ON条件的行不会被从表中删除.

下面例子验证DELETE子句.
从表NEWPRODUCTS中合并行到表PRODUCTS中, 但删除category为ELECTRNCS的行.
产品ID为1502的行从表PRODUCTS中被删除, 因为它同时匹配ON条件和DELETE WHERE条件.
产品ID为1501的行匹配DELETE WHERE条件但不匹配ON条件, 所以它没有被删除.
产品ID为1700 的行不匹配ON条件, 所以被插入表PRODUCTS.
产品ID为1601和1666的行匹配ON条件但不匹配DELETE WHERE条件, 所以被更新为表NEWPRODUCTS中的值.

SQL> MERGE INTO products p
2 USING newproducts np
3 ON (p.product_id = np.product_id)
4 WHEN MATCHED THEN
5 UPDATE
6 SET p.product_name = np.product_name,
7 p.category = np.category
8 DELETE WHERE (p.category = 'ELECTRNCS')
9 WHEN NOT MATCHED THEN
10 INSERT
11 VALUES (np.product_id, np.product_name, np.category)
SQL> /

4 rows merged.

SQL> SELECT * FROM products;

PRODUCT_ID PRODUCT_NAME CATEGORY
---------- -------------------- ----------
1501 VIVITAR 35MM ELECTRNCS
1600 PLAY GYM TOYS
1601 LAMAZE TOYS
1666 HARRY POTTER TOYS
1700 WAIT INTERFACE BOOKS
SQL>rollback;

 

抱歉!评论已关闭.