Merge into的使用詳解

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有以下一些改進: 
一、UPDATE或INSERT子句是可選的 
二、UPDATE和INSERT子句能夠加WHERE子句 
三、在ON條件中使用常量過濾謂詞來insert全部的行到目標表中,不須要鏈接源表和目標表 
四、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
相關文章
相關標籤/搜索