Sql 中 Merge 的用法

                                                               Sql 2008 Merge 的用法

Merge Sql2008 新增命令之一,它可以基于两表连接的某个条件的结果操作数据 (INSERT, UPDATE, and DELETE), 它的好处是少写一些代码,多做一些事情, 以下我们将充分说明这个优点。

有这样一个需求:

USE tempdb;

 

IF OBJECT_ID('dbo.Customers', 'U') IS NOT NULL DROP TABLE dbo.Customers;

GO

 

CREATE TABLE dbo.Customers

(

  custid      INT         NOT NULL,

  companyname VARCHAR(25) NOT NULL,

  phone       VARCHAR(20) NOT NULL,

  address     VARCHAR(50) NOT NULL,

  CONSTRAINT PK_Customers PRIMARY KEY(custid)

);

 

INSERT INTO dbo.Customers(custid, companyname, phone, address)

VALUES

  (1, 'cust 1', '(111) 111-1111', 'address 1'),

  (2, 'cust 2', '(222) 222-2222', 'address 2'),

  (3, 'cust 3', '(333) 333-3333', 'address 3'),

  (4, 'cust 4', '(444) 444-4444', 'address 4'),

  (5, 'cust 5', '(555) 555-5555', 'address 5');

IF OBJECT_ID('dbo.CustomersStage', 'U') IS NOT NULL DROP TABLE dbo.CustomersStage;

GO

 

CREATE TABLE dbo.CustomersStage

(

  custid      INT         NOT NULL,

  companyname VARCHAR(25) NOT NULL,

  phone       VARCHAR(20) NOT NULL,

  address     VARCHAR(50) NOT NULL,

  CONSTRAINT PK_CustomersStage PRIMARY KEY(custid)

);

 

INSERT INTO dbo.CustomersStage(custid, companyname, phone, address)

VALUES

  (2, 'AAAAA', '(222) 222-2222', 'address 2'),

  (3, 'cust 3', '(333) 333-3333', 'address 3'),

  (5, 'BBBBB', 'CCCCC', 'DDDDD'),

  (6, 'cust 6 (new)', '(666) 666-6666', 'address 6'),

  (7, 'cust 7 (new)', '(777) 777-7777', 'address 7');

 

要求将dbo.CustomersStage中的数据合并入dbo.Customers,合并规则如下:

a.  dbo.Customers dbo.CustomersStage 都有的一模一样的数据在dbo.Customers中保持不变

b.  dbo.Customers dbo.CustomersStage custid 相同的则按照dbo.CustomersStage中的companyname, phone, address数据更新对应的dbo.Customers数据

c.  不存在于dbo.Customerscustid)中,但存在于dbo.CustomersStagecustid)的数据要插入dbo.Customers

 

大家也许可以用多条Sql来解决:

                规则a 不需要操作

               Sql for 规则b:

             Update C

set C.companyname = cs.companyname,

    C.phone = cs.phone,

    C.address =cs.address

from dbo.Customers as C

inner join dbo.CustomersStage CS

   on CS.custid = C.custid

           Sql for 规则c:

        insert into

dbo.Customers(custid, companyname, phone, address)

select custid, companyname, phone, address

from dbo.CustomersStage where custid not in

(select custid from dbo.Customers)

 

下面看看使用Merge解决这个问题的语句:

MERGE INTO dbo.Customers AS TGT

USING dbo.CustomersStage AS SRC

  ON TGT.custid = SRC.custid

WHEN MATCHED THEN

  UPDATE SET

    TGT.companyname = SRC.companyname,

    TGT.phone = SRC.phone,

    TGT.address = SRC.address

WHEN NOT MATCHED THEN

  INSERT (custid, companyname, phone, address)

  VALUES (SRC.custid, SRC.companyname, SRC.phone, SRC.address);

如果再加一条规则d:删除dbo.Customerscustid 不在dbo.CustomersStage中的记录

如果不用merge 就要再加一句:

  delete from dbo.Customers

  where custid not in

  (select custid from dbo.CustomersStage)

 

但如果用merge,注意高亮部分是为规则d加的:

MERGE dbo.Customers AS TGT

USING dbo.CustomersStage AS SRC

  ON TGT.custid = SRC.custid

WHEN MATCHED THEN

  UPDATE SET

    TGT.companyname = SRC.companyname,

    TGT.phone = SRC.phone,

    TGT.address = SRC.address

WHEN NOT MATCHED THEN

  INSERT (custid, companyname, phone, address)

  VALUES (SRC.custid, SRC.companyname, SRC.phone, SRC.address)

WHEN NOT MATCHED BY SOURCE THEN

  DELETE;

 

但是这里有个问题,当custid在两个表中匹配上时,无论对应的记录是否一致,以上语句都是要更新dbo.Customers的,这样如果相同的很多,不起作用的update就浪费了很多资源,解决的办法(高亮部分)是:

MERGE dbo.Customers AS TGT

USING dbo.CustomersStage AS SRC

  ON TGT.custid = SRC.custid

WHEN MATCHED AND

       (   TGT.companyname <> SRC.companyname

        OR TGT.phone       <> SRC.phone

        OR TGT.address     <> SRC.address) THEN

  UPDATE SET

    TGT.companyname = SRC.companyname,

    TGT.phone = SRC.phone,

    TGT.address = SRC.address

WHEN NOT MATCHED THEN

  INSERT (custid, companyname, phone, address)

  VALUES (SRC.custid, SRC.companyname, SRC.phone, SRC.address);

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值