写在前面的话:上一篇写了如何理解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最后结果为:

  (2)照此思路,如果Then update set st.sname=ss.sname改成Then delete,自然只是红色框中部分被删除,最后Student_Target结果如下图,仅仅留下了一行。

  (3)照此思路,如果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的思路去梳理一下:

  (1)上面的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的运行结果为:

  (2)照此思路,如果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 来理解了,具体理解过程仿照第二部分,就不详细写了,直接上结果吧:

  同样原始表格还是表一和表二,贴图如下:

  (1)执行如下SQL语句:select * from Student_Target as st left outer join Student_Source as ss on st.Sno=ss.Sno,左外部联接后,结果如下图:

 

  (2)执行下面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中没有的行。

  (2)执行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

(完)

文档信息

如何理解T-SQL中Merge语句(二)的更多相关文章

  1. 如何理解T-SQL中Merge语句

    写在前面的话:之前看过Merge语句,感觉没什么用,完全可以用其他的方式来替代,最近又看了看Merge语句,确实挺好用,可以少写很多代码,看起来也很紧凑,当然也有别的优点. ====正文开始===== ...

  2. SQL中Merge的用法

    SQL中Merge的用法 Merge的用法 Merge可以完成以下功能: 1.  两个表之间数据的更新 2.  进行进销存更新库存 3.  进行表之间数据的复制 语法说明: 1.  在语句结束后一定要 ...

  3. SQL中常见语句

    SQL中常见语句笔记: --替换字段中的回车符和换行符 ) ), '') --删除表命令 DROP TABLE [dbo].[MGoods_Test] --删除表中数据命令 DELETE FROM [ ...

  4. Oracle中MERGE语句的使用

    Oracle在9i引入了merge命令, 通过这个merge你能够在一个SQL语句中对一个表同时执行inserts和updates操作. 当然是update还是insert是依据于你的指定的条件判断的 ...

  5. SQL Server Merge语句的使用

    Merge关键字在SQL Server 2008被引入,它能将Insert,Update,Delete简单的并为一句.MSDN对于Merge的解释非常的短小精悍:”根据与源表联接的结果,对目标表执行插 ...

  6. Oracle 中MERGE语句的用法

    原文章出处(http://blog.csdn.net/lichkui/article/details/4306299) MERGE语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语 ...

  7. SQL 中 SELECT 语句的执行顺序

    好像自已在书写 SQL 语句时由于不清楚各个关键字的执行顺序, 往往组织的 SQL 语句缺少很好的逻辑, 凭感觉 "拼凑" ( 不好意思, 如果您的 SQL 语句也经常 " ...

  8. SQL中查询语句的使用

    常用SQL查询语句 - myLittleGarden - 博客园 http://www.cnblogs.com/sunada2005/p/3411873.html 一.简单查询语句 1. 查看表结构 ...

  9. 【SQL】SQL 中Select语句完整的执行顺序

    SQL Select语句完整的执行顺序: 1.from子句组装来自不同数据源的数据: 2.where子句基于指定的条件对记录行进行筛选: 3.group by子句将数据划分为多个分组: 4.使用聚集函 ...

随机推荐

  1. 【iOS atomic、nonatomic、assign、copy、retain、weak、strong】的定义和区别详解

    一.atomic与nonatomic 1.相同点 都是为对象添加get和set方法 2.不同点 atomic为get方法加了一把安全锁(及原子锁),使得方法get线程安全,执行效率慢 nonatomi ...

  2. windows下node环境配置

    1.在node官网上下载合适版本的node安装包,官网地址:http://nodejs.org/#download:我下载的6.5最新版本: 2.安装node,都是系统默认的,一直安装下去: 3.在c ...

  3. 国外程序员整理的Java资源大全分享

    Java 几乎是许多程序员们的入门语言,并且也是世界上非常流行的编程语言.国外程序员 Andreas Kull 在其 Github 上整理了非常优秀的 Java 开发资源,推荐给大家. 译文由 Imp ...

  4. MyEclipse创建Maven工程

    先要在MyEclipse中对Maven进行设置:

  5. iOS之TimeLine(时间轴)的实现

    这是一个关于OC时间轴的简单实现,我认为重要的是思路. 感谢作者:Cyandev 的文章<iOS 实现时间线列表效果>给的思路.这里先附上Objective-C的代码实现,有时间再去试试S ...

  6. 【面试题】M

    一面: 1.介绍实习项目: 2.计算二叉树叶子节点的数量: 3.排序算法有哪些,手写快排: 4.长度为100的数组,值为1~100,乱序,将其中一个值改为0,找出被更改的值以及位置: 5.输入数值0~ ...

  7. ASP.NET中使用UpdatePanel实现局部异步刷新方法和攻略(转)

    asp.net UpdatePanel实现异步局部刷新 如有雷同,不胜荣欣,若转载,请注明 鉴于最近项目需要,研究了一下UpdatePanel控件的使用方法,现总结如下,可能有很多地方不足,还望大家斧 ...

  8. 北京电子科技学院(BESTI)实验报告5

    北京电子科技学院(BESTI)实验报告5 课程: 信息安全系统设计基础 班级:1452.1453 姓名:(按贡献大小排名) 郑凯杰.周恩德 学号:(按贡献大小排名) 20145314.20145217 ...

  9. 【C++设计模式】单件类与DCLP(Double Check Lock Pattern)的风险

    [单件类] 保证只能有一个实例化对象,并提供全局的访问入口. [设计注意事项] 1.阻止所有实例化的方法: private 修饰构造函数,赋值构造函数,赋值拷贝函数. 2.定义单实例化对象的方法: a ...

  10. # git 操作拾遗

    如何删除本地库 find . -name ".git" | xargs rm -Rf fatal: refusing to merge unrelated histories gi ...