• SQL Server 2008中SQL增强功能点Merge


    sql server 2008提供了一个增强的Sql命令Merge,用法参看MSDN。能根据两张表数据的不同,对两张表进行数据执行插入,更新或删除等操作,一般用在数据的抽取,例如,根据在另一个表中找到的差异在一个表中插入、更新或删除行,可以对两张表数据进行同步。

    看例子,假如,有一总产品列表,一个分店产品列表,需要从分店添加产品时更新产品列表。

    总产品表,分店产品表结构完全一致:

    if OBJECT_ID('Demo_AllProducts')is not null 
    drop table Demo_AllProductsgo
    Create table Demo_AllProducts
    (
    PKID int not null identity(1,1) primary key,
    DName Nvarchar(20) null,
    DCode NVarchar(30) null,
    DDate datetime null
    )
    go

    创建分店表

    if OBJECT_ID('Demo_Shop1_Product') is not null
    drop table Demo_Shop1_Product
    go
    Create table Demo_Shop1_Product
    (
    PKID int not null identity(1,1) primary key,
    DName Nvarchar(20) null,
    DCode NVarchar(30) null,
    DDate datetime null
    )
    go

    总店录入数据:

     Insert into Demo_AllProducts(DName,DCode,DDate)
    values
    ('DemoA','AAA',GETDATE()),
    ('DemoB','BBB',GETDATE()),
    ('DemoC','CCC',GETDATE()),
    ('DemoD','DDD',GETDATE()),
    ('DemoE','EEE',GETDATE())
    1    DemoA    AAA    2012-01-29 17:57:34.110
    2 DemoB BBB 2012-01-29 17:57:34.110
    3 DemoC CCC 2012-01-29 17:57:34.110
    4 DemoD DDD 2012-01-29 17:57:34.110
    5 DemoE EEE 2012-01-29 17:57:34.110

    分店同样的录入数据:

     Insert into Demo_Shop1_Product
    (DName,DCode,DDate)
    values
    ('DemoA','AAA',GETDATE()),
    ('DemoB','CCC',GETDATE()),
    ('DemoF','FFF',GETDATE())
    1    DemoA    AAA    2012-01-29 18:01:38.797
    2 DemoB CCC 2012-01-29 18:01:38.797
    3 DemoF FFF 2012-01-29 18:01:38.797

    假定现在需要将分店数据完全合并到总产品表中,以编码字段为依据,如果产品名称不一致,则用分店的产品名称替换总产品名称。如果总产品表中不存在,则添加。这里要区分下源表是分店表,目标表是总产品表

    可选项:如果分店表中不存在,则从总店表中删除分店中没有的行,如果这样,总产品表和分店表就完全同步了。实际操作中可能不需要删除目标表的行

    看语句:

     --确定目标表
    merge into Demo_AllProducts p

    --从数据源查找编码相同的产品
    using Demo_Shop1_Product s
    on p.DCode=s.DCode
    --如果编码相同,则更新目标表的名称
    when Matched and p.DName<>s.DName then update set p.DName=s.DName
    --如果目标表中不存在,则从数据源插入目标表中
    when not Matched by Target then Insert (DName,DCode,DDate) values (s.DName,s.DCode,s.DDate);

    --如果数据源的行在源表中不存在,则删除源表行
    --when not Matched by source then delete;

    执行后结果:

    7    DemoA    AAA    2012-01-29 18:20:40.477
    8 DemoB BBB 2012-01-29 18:20:40.477
    9 DemoB CCC 2012-01-29 18:20:40.477
    10 DemoD DDD 2012-01-29 18:20:40.477
    11 DemoE EEE 2012-01-29 18:20:40.477
    12 DemoF FFF 2012-01-29 18:20:48.073

    可以看到源表中的数据已经顺利的并入到了目标表中,如果需要记录Merge语句影响的行,可以用output子句,如果仅仅需要知道影响的行数,可以使用@@Rowcount或Rowcount_big(),修改后的实例如下:

     --定义表变量以存储输出
    Declare @tableVarRecord
    Table
    (
    MPKID int not null identity(1,1) primary key,
    PKID int null ,
    DName Nvarchar(20) null,
    DCode NVarchar(30) null,

    DDate datetime null)
    --确定目标表
    Merge Into Demo_AllProducts p
    --从数据源查找编码相同的产品
    using Demo_Shop1_Product s
    on p.DCode=s.DCode
    --如果编码相同,则更新目标表的名称
    When Matched and P.DName<>s.DName Then Update set P.DName=s.DName
    --如果目标表中不存在,则从数据源插入目标表
    When Not Matched By Target Then Insert (DName,DCode,DDate) values (s.DName,s.DCode,s.DDate)
    --如果数据源的行在源表中不存在,则删除源表行
    When Not Matched By Source Then Delete
    OUTPUT deleted.* INTO @tableVarRecord;
    ----Delete OUTPUT Inserted.* INTO @tableVarRecord;
    --返回上个Merge语句影响的行数
    select @@ROWCOUNT as Count1,ROWCOUNT_BIG() as Count2
    select * from @tableVarRecord;
  • 相关阅读:
    从构建分布式秒杀系统聊聊限流特技
    轻快的VIM(三):删除
    shell中各种括号的作用()、(())、[]、[[]]、{}
    java的重写规则
    UNIX命令,统计当前目录(含子目录)下所有后缀为.log的文件中ERROR出现的行数
    linux下使用 du查看某个文件或目录占用磁盘空间的大小
    linux如何查看系统占用磁盘空间最大的文件及让文件按大小排序
    管道命令和xargs的区别(经典解释)
    JAVA 一个或多个空格分割字符串
    shell替换一个或多个空格为逗号
  • 原文地址:https://www.cnblogs.com/zhijianliutang/p/2331383.html
Copyright © 2020-2023  润新知