傅老師課堂:Oracle高級應用之合併MERGE

爲了方便大家學習和測試,所有的例子都是在Oracle自帶用戶Scott下建立的。

MERGE是什麼?這麼厲害的東西你都不知道,你這學生是怎麼學習的?老師不給你講你就不會自學了嗎?哎!可憐天下老師心啊,罷了罷了,老師現在給你好好講一下吧。
MERGE是Oracle9i新增的語法,中文意思是“合併”,那合併什麼呢?它能合併INSERT和UPDATE在一條SQL語句中執行,是不是很牛X?!還有更牛X的,就是在執行該條語句時只做一次全表掃描,效率非常高。是不是有點心癢難耐了,哈哈,不着急,老師接下來給你具體講講它的用法。不過在講之前我們需要做兩點準備工作:
一、創建測試表且填充測試數據

  1. create table merge_test as select * from scott.dept  
二、修改測試表的數據,爲了與原表scott.dept的數據產生差異。
  1. delete from merge_test t where t.deptno=10  
  1. update merge_test t set t.dname = 'TEST'  
OK,那現在客戶提出一個需求,讓表merge_test中的機構信息與scott.dept表保持一致。

這個太簡單了,執行下面的兩條SQL語句不就可以了?!
  1. delete from merge_test  
  1. insert into merge_test select * from scott.dept  
不得不說這位同學確實有過人之處,這個別人想都不敢想的方法都被他想到了,老師只能說:“我要是你爸,當年你就在牆上了”。雖然說此方法確實到達了“目的”,但是卻太不完善了,如果客戶只想要保證機構名稱字段一致即可呢?此方法肯定便祕了,還有誰有更好的方法?

有!有!有!先把scott.dept表中的字段dname值更新到表merge_test的字段dname。
  1. update merge_test m  
  2.    set dname =  
  3.        (select dname from scott.dept t where m.deptno = t.deptno)  
再把沒在merge_test表中而在scott.dept表中的數據插入表merge_test。
  1. insert into merge_test m  
  2.   select *  
  3.     from scott.dept  
  4.    where deptno not in (select deptno from merge_test)  
這位同學還不錯,有點SQL基礎,很好,爲了激勵其他同學能想出更好的方法,老師決定下課後給這位同學買小布丁吃。不過是否還有更好更便捷的方法呢?我想同學們的水平應該也就到這,那老師就不再謙虛了(老師是幹什麼使的?老師就是在你們不知道的時候讓你們知道,在你們都知道的時候回家睡大覺)。下面老師就給你們講一種更加高級的方法,先看SQL語句。
  1. merge into merge_test m using scott.dept t on(m.deptno = t.deptno) when  
  2.    matched then update set m.dname = t.dname when not matched then insert values(t.deptno, t.dname, t.loc)  
給同學解釋一下上面的語句,把表scott.dept中的數據根據關聯條件m.deptno = t.deptno更新到merge_test表中,如果表merge_test中的deptno在表scott.dept中存在(matched 匹配),則執行更新操作update set m.dname = t.dname,如果表merge_test中的deptno在表scott.dept中不存在(not matched 不匹配),則執行插入操作insert values(t.deptno, t.dname, t.loc)。

一些聰明的同學可能會問了,只能全表操作嗎?可不可以根據篩選條件來操作呢?這樣的同學真讓人省心,你說老師能不喜歡嗎?!針對這個問題,答案是肯定的,比如我只想更新deptno=20的部門名稱,修改後的SQL語句如下:
  1. merge into merge_test m using scott.dept t on(m.deptno = t.deptno) when  
  2.    matched then update set m.dname = t.dname  
  3.    where (m.deptno = 20) when not matched then insert values(t.deptno, t.dname, t.loc)  
爲了表達老師是一位可愛的、正直的、無私的、(此處省略掉1500字褒義詞)人,老師決定在本節課最後贈送另外一個“小禮品”給同學們。在該語法中甚至還可以使用delete,如果表merge_test中的deptno在表scott.dept中存在則刪除deptno=20的機構信息,修改後的SQL語句如下:
  1. merge into merge_test m using scott.dept t on(m.deptno = t.deptno) when  
  2.    matched then update set m.dname = t.dname delete  
  3.    where (m.deptno = 20) when not matched then insert values(t.deptno, t.dname, t.loc)  
好了現在老師可以下課回家睡覺了,GOOD GOOD STUDY, DAY DAY UP.

備註:where與delete的語法是Oracle10i新增的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章