写在前面的话:之前看过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结合起来应该能够很好的解释清楚,可是现在还无法用很好的文字逻辑去表达清楚,回头想好怎么写了再写吧,请原谅我又”胡思乱想“了。

  备注:上面的结已经解开了,可以看下一篇博文:如何理解T-SQL中Merge语句(二)

(完)

文档信息

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

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

    写在前面的话:上一篇写了如何理解T-SQL中Merge语句,基本把Merge语句要讲的给讲了,在文章的后面,抛出了几个结,当时没有想明白怎么去用文字表达,这一篇就来解答一下这几个结,又是一篇“天马行空 ...

  2. SQL中Merge的用法

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

  3. SQL中常见语句

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

  4. SQL Server Merge语句的使用

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

  5. Oracle中MERGE语句的使用

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

  6. Oracle 中MERGE语句的用法

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

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

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

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

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

  9. SQL中查询语句的使用

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

随机推荐

  1. The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties

    出现这个错误提示可以用 DbFunctions.TruncateTime 将Linq中entity的DateTime转化一下再使用,如下所示: var anyCalls = _db.CallLogs. ...

  2. VadRoot枚举进程模块在Windows7下的完整实现

      原理小伟的小伟在http://bbs.pediy.com/showthread.php?t=66886说的挺清楚了,Windows7下有一些变化,使用NtQueryVirtualMemory来枚举 ...

  3. 亚马逊S3下载上传文件

    引用网址: http://www.jxtobo.com/27697.html 下载 CloudBerry Explorer http://www.cloudberrylab.com/download- ...

  4. HashMap两种遍历方式的深入研究

    转自:http://swiftlet.net/archives/1259 HashMap的遍历有两种方式,如下所示:第一种利用entrySet的方式:   1 2 3 4 5 6 7 Map map ...

  5. Kafka、RabbitMQ、RocketMQ消息中间件的对比 —— 消息发送性能-转自阿里中间件

    引言 分布式系统中,我们广泛运用消息中间件进行系统间的数据交换,便于异步解耦.现在开源的消息中间件有很多,前段时间我们自家的产品 RocketMQ (MetaQ的内核) 也顺利开源,得到大家的关注. ...

  6. spring-data-redis 用法

  7. jq 剪切板

    文章链接 http://www.cnblogs.com/lkxsnow/p/5372665.html http://www.w3cfuns.com/notes/17735/020c2e68a60342 ...

  8. HDU 4467 分块

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4467 题意:给定n个点m条边的无向图,点被染色(黑0/白1),边带边权.然后q个询问.询问分为两种: ...

  9. bind模拟

    if (!Function.prototype.bind) { Function.prototype.bind = function(oThis) { if (typeof this !== 'fun ...

  10. PHP多级联动的学习(一)

    我尝试在ThinkCMF中实现多级联动,首先我开始看了dede的联动类别管理前后台的代码以及他的数据库,经过非常多次的尝试,我渐渐有了一点想法,并给予实施. 首先写出前台的界面.如图. 然后在数据库中 ...