Jer*_*acs 2 sql-server merge upsert
假设我有一个带有复合主键的表:
create table FooBar (
   fooId int not null,
   barId int not null,
   status varchar(20) not null,
   lastModified datetime not null, 
   constraint PK_FooBar primary key (fooId, barId)
);
现在我有一些特定的表格数据fooId,也许是这样的:
1, 1, 'ACTIVE'
1, 2, 'INACTIVE'
......我想打一个MERGE语句对待这个表格数据的权威性为fooId1只,除去任何不匹配的记录,FooBar这是fooId1,但留下的所有记录了fooId是不是 1孤单。
例如,假设该FooBar表当前具有以下数据:
1, 1, 'ACTIVE', ... (some date, not typing it out)
2, 1, 'ACTIVE', ...
1, 3, 'INACTIVE', ...
2, 2, 'INACTIVE'
我想使用上面提到的两个数据集运行合并语句,并且其中的结果数据集FooBar应如下所示:
1, 1, 'ACTIVE', ...
2, 1, 'ACTIVE', ...
1, 2, 'INACTIVE', ...
2, 2, 'INACTIVE', ...
我希望1, 3, 'INACTIVE'删除该1, 1, 'ACTIVE'行,并使用新的修改后的时间戳更新该1, 2, 'INACTIVE'行,并插入该行。我也希望fooId2 的记录保持不变。
可以在一个语句中完成吗?如果是这样,怎么办?
您可以为目标和源使用通用表表达式,并且在这些ctes中可以应用过滤器来定义要使用的行:
-- t = Target = Destination Table = Mirror from Source
-- s = Source = New Data source to merge into Target table 
declare @FooId int = 1;
;with t as (
  select fooId, barId, [status], lastModified 
  from dbo.FooBar f 
  where f.fooId = @FooId
  )
,  s as (
  select fooId, barId, [status], lastModified=sysutcdatetime() 
  from src 
  where src.fooId = @FooId
  )
merge into t with (holdlock) -- holdlock hint for race conditions
using s 
  on (s.FooId = t.FooId and s.barId = t.barId)
    /* If the records matches, update status and lastModified. */
    when matched 
      then update set t.[status] = s.[status], t.lastModified = s.lastModified
    /* If not matched in table, insert the record */
    when not matched by target
      then insert (fooId,  barId,   [status],  lastModified)
        values (s.fooId, s.barId, s.[status], s.lastModified)
    /* If not matched by source, delete the record*/
    when not matched by source
      then delete
 output $action, inserted.*, deleted.*;
extrester演示:http://rextester.com/KRAI9699
返回:
+---------+-------+-------+----------+---------------------+-------+-------+----------+---------------------+
| $action | fooId | barId |  status  |    lastModified     | fooId | barId |  status  |    lastModified     |
+---------+-------+-------+----------+---------------------+-------+-------+----------+---------------------+
| INSERT  | 1     | 2     | INACTIVE | 2017-09-06 16:21:21 | NULL  | NULL  | NULL     | NULL                |
| UPDATE  | 1     | 1     | ACTIVE   | 2017-09-06 16:21:21 | 1     | 1     | ACTIVE   | 2017-09-06 16:21:21 |
| DELETE  | NULL  | NULL  | NULL     | NULL                | 1     | 3     | INACTIVE | 2017-09-06 16:21:21 |
+---------+-------+-------+----------+---------------------+-------+-------+----------+---------------------+
merge 参考: 
MERGE语句使用警告-Aaron BertrandMerge-丹·古兹曼MERGE错误-保罗·怀特merge语句吗?-Aaron BertrandMERGE,请阅读此内容!-亚伦·伯特兰Merge语句的情况(LCK_M_RS_U锁)-Kendra Littlemerge以正确的方式编写T-SQL 语句-David Stein