寫在前面的話:上一篇寫了 如何理解T-SQL中Merge語句 ,基本把Merge語句要講的給講了,在文章的后面,拋出了幾個結,當時沒有想明白怎么去用文字表達,這一篇就來解答一下這幾個結,又是一篇“天馬行空”的文字,大家湊合看吧。
===正文開始===
先看下面表一(Student_Target)和表二(Student_Source)。
一、When Matched部分
執行下面SQL語句:
MERGE INTO Student_Target AS st USING Student_Source AS ss ON st.Sno = ss.Sno WHEN MATCHED THEN UPDATE SET st.Sname = ss.Sname ;
執行完上面SQL語句后,現在的Student_Target表的內容應該也很容易得到,如下圖:
Student_Target表中Sno=1,2的行的Sname值被Student_Source中相應的值update,不過這個結果是怎么來的呢?今天用另外一種思路來理解一下怎么得到的,我們增加一個中間過程,表述如下:
(1)上面的SQL語句:MERGE INTO......WHEN MATCHED,可以類比成一個inner join語句:select * from Student_Target as st inner join Student_Source as ss on st.Sno=ss.Sno,內部聯接后,結果如下圖:
?
其中紅色框內是Student_Target部分,藍色為Student_Source部分,這個圖表示的是什么呢?我們可以認為后面執行的操作僅僅影響圖中紅色的Student_Target部分,因此,執行Then update set st.sname=ss.sname,那么原始表一Student_Target中只有 上圖紅色框中的部分受影響 ,即紅框中Sname依次被藍框內Sname給update了,其他行(3,'cc')不受影響,因此Student_Target最后結果為:
?。?)照此思路,如果Then update set st.sname=ss.sname 改成Then delete, 自然只是紅色框中部分被刪除,最后Student_Target結果如下圖,僅僅留下了一行。
?。?)照此思路,如果Then update set st.sname=ss.sname 改成Then insert values(ss.sno,ss.sname),會出現什么情況呢? 再看前面的紅色和藍色部分,紅色部分內容不為NULL,因此無法用右邊的藍色部分給insert進去,所以應該報錯,執行一下,果然報下面的錯誤:
現在應該明白When Matched為什么不允許有insert語句了吧,那么什么時候允許insert語句呢,接著往下看。
二、When NOT Matched BY Target部分
前面When Matched我們通過inner join的思路進行了理解,這次When NOT Matched BY Target我們用right outer join的思路去想想,同樣原始表格還是表一和表二,再次貼圖如下:
執行下面SQL語句:
MERGE INTO Student_Target AS st USING Student_Source AS ss ON st.Sno = ss.Sno WHEN NOT MATCHED BY TARGET THEN INSERT VALUES(ss.Sno,ss.Sname) ;
先不用著急看上面運行結果,我們先用right outer join的思路去梳理一下:
?。?)上面的SQL語句:MERGE INTO......WHEN NOT MATCHED BY TARGET,可以類比成一個right outer join語句:select * from Student_Target as st right outer join Student_Source as ss on st.Sno=ss.Sno,右外部聯接后(你應該對right outer join 概念非常清晰吧),結果如下圖:
?
其中紅色框內是Student_Target部分,藍色為Student_Source部分,這個圖表示的是什么呢?我們可以認為后面執行的操作僅僅影響圖中紅色的Student_Target部分,因此,執行Then insert values(ss.Sno,ss.Sname),那么原始表一Student_Target中只有 上圖紅色框中的部分受影響 ,即紅框中Sno和Sname為null的依次被藍框內Sno和Sname給insert了,這里之所以可以insert,就是因為第三行和第四行里面有null的值,因此最后Student_Target的運行結果為:
?。?)照此思路,如果Then insert values(ss.Sno,ss.Sname) 改成Then delete, 自然只是紅色框中部分被刪除,但是紅色部分的第三行和第四行是全為NULL的值,全null了自然無法刪除啊,因此應該報錯,運行一下,果然報錯如下:
(3)照此思路,如果Then insert values(ss.Sno,ss.Sname) 改成Then update set st.Sname=ss.Sname ,同樣因為全null的行會報錯,因為全null無法更新啊,報錯信息如下:
現在應該明白When NOT Matched BY Target為什么不允許有update和delete語句了吧。
三、When NOT Matched BY SOURCE部分
前面When Matched我們通過inner join的思路進行了理解,When NOT Matched BY Target用right outer join的思路去理解了,這次的When not matched by source自然應該用left outer join 來理解了,具體理解過程仿照第二部分,就不詳細寫了,直接上結果吧:
同樣原始表格還是表一和表二,貼圖如下:
?。?)執行如下SQL語句:select * from Student_Target as st left outer join Student_Source as ss on st.Sno=ss.Sno,左外部聯接后,結果如下圖:
?。?)執行下面SQL語句:
MERGE INTO Student_Target AS st USING Student_Source AS ss ON st.Sno = ss.Sno WHEN NOT MATCHED BY SOURCE THEN delete ;
最后Student_Target的運行結果為:
?
刪除了Student_Target中有而Student_Source中沒有的行。
?。?)執行insert和update語句同樣報錯。
四、最后總結
很佩服你竟然能看到這里,最后來一個總結吧:
(1)when matched:類比inner join去思考,可以執行update和delete操作,無法執行insert操作。
(2)when not matched by target:類比right outer join去思考,可以執行insert操作,無法執行update和delete操作。 (target表中沒有(not matched),而source表中有)
(3)when not matched by source,類比left outer join去思考,可以執行delete 操作,無法執行insert和update操作。 (target表中有,而source表中沒有(not matched))
?
?
備注:練習過程中用到的代碼:
?
USE testDB GO MERGE INTO Student_Target AS st USING Student_Source AS ss ON st.Sno = ss.Sno --WHEN MATCHED --THEN UPDATE SET st.Sname = ss.Sname --THEN INSERT VALUES(ss.sno,ss.sname) --WHEN NOT MATCHED BY TARGET --THEN UPDATE set st.sname=ss.sname --WHEN NOT MATCHED BY SOURCE --THEN UPDATE set st.Sname=ss.Sname,st.Sno=ss.Sno ; TRUNCATE TABLE dbo.Student_Target TRUNCATE TABLE dbo.Student_Source insert into Student_Target (sno,sname)values(1,'aa'),(2,'bb'),(3,'cc') insert into Student_Source (sno,sname)values(1,'xiaoming'),(2,'xiaoli'),(4,'xiaohong'),(5,'xiaoping') SELECT * FROM dbo.Student_Target SELECT * FROM dbo.Student_Source SELECT * FROM dbo.Student_Target AS st INNER JOIN dbo.Student_Source AS ss ON st.Sno=ss.Sno SELECT * FROM dbo.Student_Target AS st RIGHT OUTER JOIN dbo.Student_Source AS ss ON st.Sno=ss.Sno SELECT * FROM dbo.Student_Target AS st LEFT OUTER JOIN dbo.Student_Source AS ss ON st.Sno=ss.Sno
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
