Merge into的使用具体解释-你Merge了没有

 

Merge是一个很实用的功能,相似于Mysql里的insert into on duplicate key. 

Oracle在9i引入了merge命令, 
通过这个merge你可以在一个SQL语句中对一个表同一时候运行inserts和updates操作. 当然是update还是insert是根据于你的指定的条件推断的,Merge into可以实现用B表来更新A表数据,假设A表中没有,则把B表的数据插入A表. MERGE命令从一个或多个数据源中选择行来updating或inserting到一个或多个表 

语法例如以下 
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 MATHED THEN [here you can execute some update sql or something else ] 
WHEN NOT MATHED THEN [execute something else here ! ] 

我们先看看一个简单的样例,来介绍一个merge into的使用方法 
merge into products p using newproducts np on (p.product_id = np.product_id) 
when matched then 
update set p.product_name = np.product_name 
when not matched then 
insert values(np.product_id, np.product_name, np.category) 

在这个样例里。前面的merger into products using newproducts 表示的用newproducts表来merge到products表,merge的匹配关系就是on后面的条件子句的内容,这里依据两个表的product_id来进行匹配,那么匹配上了我们的操作是就是when matched then的子句里的动作了,这里的动作是update set p.product_name = np.product_name, 非常显然就是把newproduct里的内容,赋值到product的product_name里。假设没有匹配上则insert这种一条语句进去。 大家看看这个merget inot的使用方法是不是一目了然了呀。这里merger的功能,好比比較,然后选择更新或者是插入,是一系列的组合拳,在做merge的时候,这样相同的情况下,merge的性能是优于同等功能的update/insert语句的。有人以前分析merge是批量处理对性能贡献非常大,个人认为这个是没有考据的。 

我们也能够在using后面使用视图或者子查询。比方我们把newproducts换成 
merge into products p using (select * from newproducts) np on (p.product_id = np.product_id) 
when matched then 
update set p.product_name = np.product_name 
when not matched then 
insert values(np.product_id, np.product_name, np.category) 
也是能够的。 

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

我们通过实例来一一看看如上的新特性 

1. UPDATE或INSERT子句是可选的 
在9i里因为必须insert into和update都要存在,也就是不是update就是insert,不支持单一的操作,尽管还是能够曲线救国,呵呵 可是有些过于强势了。而10g里就是可选了,能符合我们很多其它的需求了 
比方上面的句子 
我们能够仅仅存在update或者insert 
merge into products p using newproducts np on (p.product_id = np.product_id) 
when matched then 
update set p.product_name = np.product_name 
这里,假设匹配就更新,不存在就无论了。 

2. UPDATE和INSERT子句能够加WHERE子句 
这也是一个功能性的改进,可以符合我们很多其它的需求,这个where的作用非常明显是一个过滤的条件,是我们增加一些额外的条件,对仅仅对满足where条件的进行更新和insert 
merge into products p using (select * from newproducts) np on (p.product_id = np.product_id) 
when matched then 
update set p.product_name = np.product_name where np.product_name like 'OL%' 
这里表示仅仅是对product_name开头是'OL'的匹配上的进行update,假设开头不是'OL'的就是匹配了也不做什么事情,insert里也能够增加where 
比方 
merge into products p using (select * from newproducts) np on (p.product_id = np.product_id) 
when matched then 
update set p.product_name = np.product_name where np.product_name like 'OL%' 
when not matched then 
insert values(np.product_id, np.product_name, np.category) where np.product_name like 'OL%' 

这里注意比較一下,他们返回的结果行数,是有着差异的。 

3. 在ON条件中使用常量过滤谓词来insert全部的行到目标表中,不须要连接源表和目标表 

merge into products p using (select * from newproducts) np on (1=0) 
when matched then 
update set p.product_name = np.product_name 
when not matched then 
insert values(np.product_id, np.product_name, np.category) 
个人认为这个功能没有太大的意义,我们的insert into本身就支持这种功能,没有必要使用merge 

4. UPDATE子句后面能够跟DELETE子句来去除一些不须要的行 
delete仅仅能和update配合,从而达到删除满足where条件的子句的纪录 
merge into products p using (select * from newproducts) np on (p.product_id = np.product_id) 
when matched then 
update set p.product_name = np.product_name delete where p.product_id = np.product_id where np.product_name like 'OL%' 
when not matched then 
insert values(np.product_id, np.product_name, np.category) 
这里我们达到的目的就是 会把匹配的记录的prodcut_name更新到product里,而且把product_name开头为OL的删除掉。

merge into也是一个dml语句,和其它的dml语句一样须要通过rollback和commit 结束事务。 

Merge是一个很强大的功能,并且是我们需求里常常会用到的一个实用的功能,所以我们一定要好好的学习到。 

文中须要的測试脚本在附件里提供下载。 
merge into sample.sql




 

posted @ 2015-05-09 17:14  lcchuguo  阅读(183)  评论(0编辑  收藏  举报