SQL点滴18—SqlServer中的merge操作,相当地风骚

来源:网络 责任编辑:栏目编辑 发表时间:2013-07-01 17:08 点击:

今天在一个存储过程中看见了merge这个关键字,第一个想法是,这个是配置管理中的概念吗,把相邻两次的更改合并到一起。后来在technet上搜索发现别有洞天,原来是另外一个sql关键字,t-sql的语法还是相当地丰富的。本篇是一篇学习笔记,没有什么新意,这里具体的语法不去深究了,只是把几个例子实际运行,剖析一番。

  

使用merge同时执行insert和update操作

我们经常会有这样的需求,根据某个字段或多个字段查找表中的一行或多行数据,如果查找成功得到匹配项,更新其中的其他一个或多个字段;如果查找失败则将“某个字段或多个字段”作为新的一行中的数据插入到表中。第一种方法是先更新,然后根据@@rowcount判断是否有匹配项,如果没有则插入。先使用下面的 代码创建一个存储过程。

 1 use AdventureWorks 2 go 3 create procedure dbo.InsertUnitMeasure @UnitMeasureCode nchar(3),@Name nvarchar(25) 4 as 5 begin 6 set nocount on; 7 update Production.UnitMeasure set Name=@Name where UnitMeasureCode=@UnitMeasureCode 8 if(@@ROWCOUNT=0) 9   begin10   insert into Production.UnitMeasure(Name,UnitMeasureCode)values(@Name,@UnitMeasureCode)11   end12 end13 go记得见过这样的笔试题目,要求是插入不存在的行,只要把上面语句中的update改成select就可以了,当时没有写出来,现在恍然大悟,也许是在考察@@ROWCOUNT的用法吧。这个语句也可以使用merge语句实现。下面我们使用merge关键字来修改这个存储过程。

 1 alter procedure dbo.InsertUnitMeasure @UnitMeasureCode nchar(3),@Name nvarchar(25) 2 as 3 begin 4 set nocount on 5 merge Production.UnitMeasure as target 6 using (select @UnitMeasureCode,@Name) as source (UnitMeasureCode,Name) 7 on (target.UnitMeasureCode=source.UnitMeasureCode) 8 when matched then update set Name=source.Name 9 when not matched then insert(UnitMeasureCode,Name)values(source.UnitMeasureCode,Name)10 output deleted.*,$action,inserted.* into MyTempTable;11 end12 go这个语句使用merge修改存储过程,这个语句中又出现我不太了解的关键字using和$action。Using是用来指定和表InsertUnitMeasure中相匹配的数据源,这里的数据源来自外部输入,是通过两个输入参数得到。$action可能是一个占位符,表示上面的when字句进行的操作。至于inserted.*和deleted.* 就是插入和删除的数据行了,这个我在其中一篇文章中也提到,他们有点类似类中的this关键字,过可以看看:SQL点滴14—编辑数据。注意为了记录修改的过程我们需要创建一个临时表#MyTempTable来跟踪修改过程,所以在调用这个存储过程之前我们需要新建这个表,语句如下:

 1 create table MyTempTable( 2 ExistingCode  nchar(3), 3 ExistingName  nvarchar(50), 4 ExistingDate  datetime, 5 ActionTaken   nvarchar(50), 6 NewCode       nchar(3), 7 [NewName]     nvarchar(50),       8 NewDate       datetime 9 )10 Go现在我们来执行下面的语句看看有什么样的结果:

1 exec InsertUnitMeasure @UnitMeasureCode = ABC,@Name=New Test Value12 EXEC InsertUnitMeasure @UnitMeasureCode = XYZ, @Name = Test Value;3 EXEC InsertUnitMeasure @UnitMeasureCode = ABC, @Name = Another Test Valuea;4 Go首先使用语句:select * from Production.UnitMeasure order by ModifiedDate desc 来查看目标表中的数据变化如图1:

图1

这里虽然三次执行了存储过程,但是由于第一次和第三次的@UnitMeasureCode的值是相同的’ABC’所以第二次肯定是进行更新操作。所以最后表中新增了两条记录。然后使用下面的语句查看记录表MyTempTable中的跟踪信息如图2

图2

我们可以看到前面两条语句执行的是插入操作,所以原有的值都是空,因为在插入之前他们还不存在。第三条新型的是更新操作,更新UnitMeasureCode为’ABC’的记录。
 
  

使用merge在单个语句中执行insert和update操作

在AdventureWorks数据库中有ProductInventory表,存储的是存货信息,SalesOrderDetail表中存储的是订单信息,现在如果每天减去对SalesOrderDetail表中每种产品所下的订单数,更新ProductInventory表中的 Quantity列。如果随着时间推移订单数导致产品库存量下降到0或者更少,则从ProductInventory表中删除该产品对应的行。下面的语句创建一个存储过程实现上面的逻辑。

 1 CREATE PROCE

    相关新闻>>

      发表评论
      请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
      用户名: 验证码:点击我更换图片
      最新评论 更多>>

      推荐热点

      • sql常见面试题
      • SQL SERVER 2005性能之跟踪
      • SQL编程(一)
      • LINUX上RMAN自动备份脚本
      • sql server面试题
      • 如何将多个SQL查询统计结果一次显示出来
      • 浅谈SQL Server中的事务日志(三)----在简单恢复模式下日志的角色
      • sql server 列转行
      • SQL小技巧系列 --- 行转列合并
      网站首页 - 友情链接 - 网站地图 - TAG标签 - RSS订阅 - 内容搜索
      Copyright © 2008-2015 计算机技术学习交流网. 版权所有

      豫ICP备11007008号-1