在更新数据仓库时,经常需要根据源表对Target表进行数据同步,Merge 命令具有数据更新,删除,插入的功能,专门用于数据同步,并将数据的更新输出到表中。在使用Merge命令时,需要注意when not matche子句:

  • when not matched by target :当Target Table不匹配时,数据行不存在于Target Table中,存在于Source Table;
  • when not matched by source:当Source Table不匹配时,数据行不存在于Source Table中,存在于Target Table;
  • 当不指定by子句时,默认值是by target;

1,创建示例数据

use tempdb
go create table dbo.tar
(
id int not null,
name varchar(11) not null
)
go
create table dbo.src
(
id int not null,
name varchar(11) not null
)
go
insert into dbo.tar
values(1,'t1'),(2,'t2'),(3,'t3')
insert into dbo.src(id,name)
values(1,'t1'),(2,'s2'),(4,'s4') create table dbo.dt_merge_output
(
action nvarchar(10) not null,
Deleted_ID int not null,
Deleted_Name nvarchar(11) not null,
Inserted_ID int not null,
Inserted_Name nvarchar(11) not null
)
go

2,同步数据,将源表的数据同步到靶表中

merge into dbo.tar as t
using dbo.src as s
on t.id=s.id --matched表示On子句匹配成功,加上额外的and条件,如果when子句成功,那么更新Targe表中的数据
when matched and t.name<>s.name
then update set t.name=s.name --not matched表示On子句不匹配
--ID不存在于Targe表,存在于Source表,则将行插入到Targe表
when not matched --default by target
then insert (id,name)
values(s.id,s.name) --ID存在于Targe表,而不存在于Source表,那么将行从Target表删除
when not matched by source
then delete;

2,使用output子句,将靶表中更新的数据输出

merge into dbo.tar as t
using dbo.src as s
on t.id=s.id --matched表示On子句匹配成功,加上额外的and条件,如果when子句成功,那么更新Targe表中的数据
when matched and t.name<>s.name
then update set t.name=s.name --not matched表示On子句不匹配
--ID不存在于Targe表,存在于Source表,则将行插入到Targe表
when not matched --default by target
then insert (id,name)
values(s.id,s.name) --ID存在于Targe表,而不存在于Source表,那么将行从Target表删除
when not matched by source
then delete
output $action,deleted.id as Deleted_ID,deleted.name as Deleted_Name,inserted.id as Instered_ID,inserted.name as Instered_Name
;

3,将靶表中更新的数据插入到一个表中有两种方式,一种是output into,一种是使用insert into

第一种方式,使用ouput into方式,将数据插入到staging table中

;merge into dbo.tar as t
using dbo.src as s
on t.id=s.id --matched表示On子句匹配成功,加上额外的and条件,如果when子句成功,那么更新Targe表中的数据
when matched and t.name<>s.name
then update set t.name=s.name --not matched表示On子句不匹配
--ID不存在于Targe表,存在于Source表,则将行插入到Targe表
when not matched --default by target
then insert (id,name)
values(s.id,s.name) --ID存在于Targe表,而不存在于Source表,那么将行从Target表删除
when not matched by source
then delete
output $action,deleted.id as Deleted_ID,deleted.name as Deleted_Name,inserted.id as Instered_ID,inserted.name as Instered_Name
into dbo.dt_merge_output
; select *
from dbo.dt_merge_output

第二种方式,将output子句的输出作为派生表,使用Insert Into子句将数据插入到staging 表中

insert into dbo.dt_merge_output
select *
from
(
merge into dbo.tar as t
using dbo.src as s
on t.id=s.id --matched表示On子句匹配成功,加上额外的and条件,如果when子句成功,那么更新Targe表中的数据
when matched and t.name<>s.name
then update set t.name=s.name --not matched表示On子句不匹配
--ID不存在于Targe表,存在于Source表,则将行插入到Targe表
when not matched --default by target
then insert (id,name)
values(s.id,s.name) --ID存在于Targe表,而不存在于Source表,那么将行从Target表删除
when not matched by source
then delete
output $action,deleted.id as Deleted_ID,deleted.name as Deleted_Name,inserted.id as Instered_ID,inserted.name as Instered_Name
) as p(Action,Deleted_ID,Deleted_Name,Instered_ID,Instered_Name)

4,Output子句

Output子句,用于输出在Target Table中更新的数据,在每个数据行中,有一个特殊的字段,$Action,数据类型是nvarchar(10),能够标识出Merge操作的类型:Insert Delete,Update。

<OUTPUT_CLAUSE> ::=
{
  [ OUTPUT <dml_select_list> INTO { @table_variable | output_table } [ ( column_list ) ] ]
  | [ OUTPUT <dml_select_list> ]
} <dml_select_list> ::= { <column_name> | scalar_expression } [ [AS] column_alias_identifier ][ ,...n ]
<column_name> ::= { DELETED | INSERTED | from_table_name } . { * | column_name }| $action

表Deleted和Inserted 是特殊的两个系统表,由系统创建,并且用户语句只能读取,不能修改,作用域是语句级别,当语句结束时,系统自动回收。DELETED 用于标识被Merge命令删除的数据行,INSERTED 用于标识被Merge命令插入的数据行,如果执行的是Update操作,那么inserted 用于标识更新之后的数据,deleted 用于标识数据行更新之前的数据。

5,在使用Merge命令更新Target表时,同一行数据只能被更新一次

If UPDATE is specified in the <merge_matched> clause, and more than one row of <table_source>matches a row in target_table based on <merge_search_condition>, SQL Server returns an error. The MERGE statement cannot update the same row more than once, or update and delete the same row.

Target表中一个数据行只能被更新一次,SQL Server会报错,错误原因是Source Table的中的多行数据和Target Table中一行数据匹配。

The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.

参考MSDN

MERGE (Transact-SQL)

TSQL Merge 用法的更多相关文章

  1. Merge用法

    Merge用来从一个表中选择一些数据更新或者插入到另一个表中.而最终是用更新还是用插入的方式取决于该语句中的条件. 下面我们简单的举一个例子:   SQL> create table merge ...

  2. Oracle之Merge用法

    Merge用来从一个表中选择一些数据更新或者插入到另一个表中.而最终是用更新还是用插入的方式取决于该语句中的条件. 下面我们简单的举一个例子: SQL)) 表已创建. SQL)) 表已创建. SQL, ...

  3. TSQL Merge On子句和When not matched 语义理解

    Merge 的On子句指定Match condition,When子句指定过滤条件,如果Source Table和Targe Table匹配的上,很好理解:如果匹配不上,必须深入理解不匹配的条件,否则 ...

  4. TSql Top 用法

    第一部分:TSql Top 有两种用法 1,限制查询结果集返回的行数或总行数的百分比. 当将 TOP 与 ORDER BY 子句结合使用时,结果集限制为前 N 个已排序行:否则,以未定义的顺序返回前 ...

  5. TSQL HASHBYTES 用法

    HashBytes 使用Hash 算法,能够产生高质量的Hash值,大幅度提高识别数据相异的准确性,但是HashBytes函数无法提供100%的准确度,如果业务逻辑要求不允许有误差,那么不要使用任何H ...

  6. MERGE 用法

    1.不带输出的SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER proc [dbo].[InsertShiGongJiao] ), @com ...

  7. oracle merge用法

    动机: 想在Oracle中用一条SQL语句直接进行Insert/Update的操作. 说明: 在进行SQL语句编写时,我们经常会遇到大量的同时进行Insert/Update的语句 ,也就是说当存在记录 ...

  8. Sql server2008中merge用法

    /// <summary> /// 修改:添加条件: AND roleModule.FuncCode = tvpRoleModule.FuncCode /// </summary&g ...

  9. SQL Server merge用法

    有两个表名:source 表和 target 表,并且要根据 source 表中匹配的值更新 target 表. 有三种情况: source 表有一些 target 表不存在的行.在这种情况下,需要将 ...

随机推荐

  1. vim指令常用

    慢慢尝试使用vim,不断学习使用新的快捷键,将常用快捷键但经常容易忘的写下来, 1. 复制黏贴 命令行模式下按住v选中,y表示复制,d表示剪切,p为复制.

  2. android wifi 获取扫描结果

    1.1 framework部分: 1.2 supplicant部分: hdd_cfg80211_scan_done_callback -> wlan_hdd_cfg80211_update_bs ...

  3. nginx切割日志

    #!/bin/bash ## Nginx 日志文件所在的目录 LOGS_PATH=/usr/local/nginx/logs ## 获取昨天的 yyyy-MM-dd YESTERDAY=$(date ...

  4. 解决ViewPage中嵌套有ListView或者滑动手势等造成滑动的冲突

    public class ViewPagerCompat extends ViewPager { //mViewTouchMode表示ViewPager是否全权控制滑动事件,默认为false,即不控制 ...

  5. ABP框架详解(四)Feature

    ABP框架中存在一个Feature的特性,功能和设计思路非常类似于框架中的Authorization功能,都是来控制用户是否能够继续操作某项功能,不同点在于Authorization默认是应用在IAp ...

  6. 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)

    好长时间没有用过Spring了. 突然拿起书.我都发现自己对AOP都不熟悉了. 其实AOP的意思就是面向切面编程. OO注重的是我们解决问题的方法(封装成Method),而AOP注重的是许多解决解决问 ...

  7. IEnumerable<IEnumerable<string>>结构解析通用解决方案(支持指定属性顺序)

    一.前言 类似如下字符串 "ID", "NameValue", "CodeValue", "ExchangeTypeValue&q ...

  8. 【腾讯Bugly干货分享】iOS黑客技术大揭秘

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5791da152168f2690e72daa4 “8小时内拼工作,8小时外拼成长 ...

  9. 如何用MediaCapture解决二维码扫描问题

    二维码扫描的实现,简单的来说可以分三步走:“成像”.“截图”与“识别”. UWP开发中,最常用的媒体工具非MediaCapture莫属了,下面就来简单介绍一下如何利用MediaCapture来实现扫描 ...

  10. MySQL3:索引

    什么是索引 索引是对数据库表中一列或者多列的值进行排序的一种结构,所引用于快速找出在某个列中有一特定值的行.不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行.表越大,查询数据所花 ...