原文:
如何理解t-sql中merge語句
寫在前面的話:之前看過merge語句,感覺沒什麼用,完全可以用其他的方式來替代,最近又看了看merge語句,確實挺好用,可以少寫很多**,看起來也很緊湊,當然也有別的優點。
====正文開始*****
sql server 2008 引入了merge關鍵字,主要是在一條語句裡面可以執行insert、update、delete操作,以實現用乙個源物件的資料對目標物件資料進行操作。注意這裡的」源物件「和」目標物件「我用黑色標註了,源物件和目標物件實際上不僅僅可以是表table,還可以是臨時表、檢視、表變數、cte,同時」目標物件「還可以是select語句,說這麼多其實想表達merge語句可以很靈活的使用,但是我們理解的話,可以把」源物件「和」目標物件「想象成table就行了,畢竟臨時表、檢視、表變數、cte也都可以想象成table。
(注意:如果目標物件是檢視的話,那麼對目標物件的操作,如update,實際上是對生成檢視的表進行操作的)。
好了,看完上面的文字,你可能已經看不下去了,之所以寫上面的話,是為了顯得嚴謹一些,接下來就用例子來講解吧,這個例子不涉及業務邏輯,可以專注於理解merge的用法,至於實際中什麼時候用,只能自己悟了,好了,開始舉例子。
例如有乙個student_target表,如下表一,另外乙個student_source表,如下表二:
執行如下sql語句:
merge into student_target as st --這裡是目標表,它將要被源表merge
using student_source as ss --這裡是源表
on st.sno = ss.sno --這裡是匹配條件
when matched --when和then是配套的,當st.sno=ss.sno時,用ss.sname更新st.sname,我們看到這裡update後面沒有寫明更新的表,這裡更新的是目標表
then update set st.sname = ss.sname
when not matched by target --目標表中不存在,而源表中存在資料,那麼就執行insert操作,這裡by target可以省略,但是建議加上
then insert values ( ss.sno,ss.sname)
when not matched by source --當目標表中存在,而源表中不存在資料,那麼就執行delete操作,這裡使用了by source
then delete
;
上面sql語句的意思可以看後面的注釋,這裡再做一簡要說明:對於表一,sno=1的一行和表二sno=1的匹配,所以表一中該行被更新;表一中sno=2,3在表二中不存在,因此delete,表二中sno=4但是在表一中不存在,因此insert,最後結果如下:
我們看到上面的結果和表二的內容是一樣的,其實你再分析一下上面的sql語句,邏輯就是把表二的內容弄進表一,表一中和表二中不一致的資料刪除,似乎我們上面的merge語句顯得很多餘。這裡想再說明幾點:
(1)我們when matched、when not matched by target、when not matched by source都寫上了,其實是可選的,我們可以根據自己的需求只使用其中的部分。
(2)前面是merge into student_target as st,其實可以增加top(n)來對特定數量的行進行操作。執行如下sql:
merge top(2) into student_target as st --這裡是目標表,它將要被源表merge
using student_source as ss --這裡是源表
on st.sno = ss.sno --這裡是匹配條件
when matched --when和then是配套的,當st.sno=ss.sno時,用ss.sname更新st.sname,我們看到這裡update後面沒有寫明更新的表,這裡更新的是目標表
then update set st.sname = ss.sname
when not matched by target --目標表中不存在,而源表中存在資料,那麼就執行insert操作,這裡by target可以省略,但是建議加上
then insert values ( ss.sno,ss.sname)
when not matched by source --當目標表中存在,而源表中不存在資料,那麼就執行delete操作,這裡使用了by source
then delete
;
最後結果如下:
所以,增加了top(2),那麼目標表可以被操作的行只能是2條,上面的update操作一條,insert操作一條,達到2條,因此後面的delete就不影響了。因此,對於top(n)應該能夠正確的理解。
(3)前面when matched 其實還可以配合其他條件一起操作,例如when matched 可以修改為when matched and ss.sno=1或者when matched and st.sno=1;對於when not matched,只能夠使用源列,也就是說,增加and ss.sno=1可以,但是增加and st.sno=1就會報錯了。
(4)merge最後一定要以分號結尾,表示這個merge句子完整了。
前面的操作我們看到預設的都是對target表的操作,有時候我們想對target表操作後,還能夠針對特定的條件,對source表進行操作,這是就可以配合output子句一起,來完成我們想要的操作。這裡output字句不單單是針對merge語句的,對於insert、update、delete等操作也可以用的,所以具體的可以再去單獨研究研究output子句。
至此,本文也該告一段落,如何使用merge語句應該也沒有問題。可是心中仍然有乙個結,正如上篇文章所寫的:如何理解group by和聚合函式中對group by和聚合函式的認識一樣,雖然用起來不成問題,但是總是希望能夠找到乙個天馬行空的想法,能夠換個角度去認識。比如為啥基本上都是when matched後面跟update,when not matched by target後面跟insert,when not matched by source 後面跟delete呢?為啥when not matched by target後面不能跟delete?為啥when not matched by source後面不能跟insert呢?當然可能還有其他疑問,目前可以跟join結合起來應該能夠很好的解釋清楚,可是現在還無法用很好的文字邏輯去表達清楚,回頭想好怎麼寫了再寫吧,請原諒我又」胡思亂想「了。
Windows XP中如何找回丟失的系統語言欄
預設情況下,windows工作列上有乙個輸入法標誌,在windows 98中被稱作輸入法圖示,在windows xp中被稱為語言欄。有時這個輸入法語言欄會突然丟失,在windows 98中,可以在 開始 執行 中輸入internat來恢復該標誌。在windows xp中該如何恢復呢?請看下面的方法 ...
應該如何理解mobx 技術人應該如何理解中臺?
你好,歡迎收聽極客視點。此前,企業it架構轉型之道 的作者 原阿里巴巴中介軟體首席架構師鍾華 古謙 在 榕錦it高管共贏圈 分享了他對中颱的理解,並 了企業在什麼發展階段該考慮中臺,以及技術人該如何理解中臺,希望能給你帶來新的思考。落地中颱最常見的問題之一就是,企業在什麼階段該考慮中臺?對此,鍾華的...
Swift 中如何理解copy on write
當值型別 如struct 在複製時,複製的物件和元 原物件實際上在記憶體中指向同乙個物件。當且僅當修改複製後的物件時,才會在記憶體中重新建立乙個新的物件。舉例 arraya是乙個陣列,為值型別 let arraya 1,2,3 arrayb這個時候與arraya在記憶體中是同乙個陣列,記憶體中並沒有...