如何理解T SQL中Merge語句

2021-09-06 20:46:31 字數 3561 閱讀 4416

原文:

如何理解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在記憶體中是同乙個陣列,記憶體中並沒有...