SQL Server 2008 Merge语句实战:实现数据的增删改同步
SQL Server 2008提供了强大的Merge语句,允许开发者在一次操作中根据源表与目标表的比较结果,同步执行插入、更新和删除操作,从而高效地保持两个表之间的数据一致性。
Merge语句的核心功能
Merge语句的主要用途是整合对目标表的多种修改动作。它通过联接源表和目标表,识别两者的差异:
- Matched:源表中存在且目标表中也有对应行时,可执行更新。
- Not Matched By Target:源表中存在但目标表中没有的行,可执行插入。
- Not Matched By Source:目标表中存在但源表中没有的行,可执行删除。
这种机制常用于将分支节点(如分店)的数据变更同步回中心节点(如总库),或反之。
准备工作:构建测试环境
为了清晰展示Merge的效果,我们首先创建结构相同的“总产品表”和“分店产品表”,并初始化基础数据。
第1步:创建总产品表Demo_AllProducts
目的:建立需要同步的中心表,包含初始的5条产品记录。
-- 如果表存在则删除
if OBJECT_ID('Demo_AllProducts') is not null drop table Demo_AllProducts go
-- 创建表结构
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
-- 插入初始数据 (SQL Server 2008支持多值INSERT)
Insert into Demo_AllProducts (DName,DCode,DDate) values
('DemoA','AAA',GETDATE()),
('DemoB','BBB',GETDATE()),
('DemoC','CCC',GETDATE()),
('DemoD','DDD',GETDATE()),
('DemoE','EEE',GETDATE());
select * from Demo_AllProducts;
第2步:创建分店产品表Demo_Shop1_Product
目的:建立作为数据源的分支表,其中部分产品编码与总表重合(如AAA, CCC),但名称不同;同时新增了总表中不存在的产品(FFF)。
-- 创建分店表
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_Shop1_Product (DName,DCode,DDate) values
('DemoA','AAA',GETDATE()),
('DemoB','CCC',GETDATE()), -- 注意:这里代码写错了示例意图,通常应该是对应另一个编码,假设意在修改现有或新增。
-- 原文示例中DemoB对应CCC,而原总表BBB对应DemoB,这里假设分店有AAA(同名), CCC(原名DemoB), FFF(新)
-- 修正逻辑以符合下文解释:分店有 'DemoA/AAA', 'DemoB/CCC' (可能是笔误,按原文执行), 'DemoF/FFF'
-- 为严谨起见,以下代码严格按原文输入:
('DemoB','CCC',GETDATE()),
('DemoF','FFF',GETDATE());
select * from Demo_Shop1_Product;
此时,总表有A,B,C,D,E五个编码;分店表有AAA, CCC, FFF三个记录。我们要以
执行数据同步操作
第3步:完整同步(含更新、插入和删除)
目的:将分店数据完全合并到总表。若编码相同且名称不同,更新名称;若总表无该编码,则插入;若分店无该编码,则从总表删除该行。
Merge Into Demo_AllProducts p -- 目标表别名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;
执行结果分析:执行完成后,总表仅保留与分店匹配的三项(AAA, CCC, FFF)。原总表中的B(BBB), C(CCC-此处因代码逻辑DCode一致被更新或删除,取决于前序状态), D, E均被移除,因为分店中没有对应的AAA/CCC/FFF以外的编码记录。最终总表内容与分店表保持一致。
第4步:仅同步新增与更新(不删除)
目的:在实际业务中,往往只需要汇总分店的增量数据到总部,而不希望删除总部原有但在分店下架的商品。此时省略Delete子句。
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);
执行后结果:
- DemoA (AAA): 名称未变,保留。
- DemoB (BBB): 总表原有,分店无,未触发删除,保留。
- DemoB (CCC): 分店有此记录(DemoB/CCC),若总表曾有同编码且名称不同则更新。注:原文示例逻辑中,分店有CCC码,总表原无CCC码(原为BBB),故触发插入?或者原文意指分店表中有一条记录其DCode为CCC。让我们细看:总表有CCC吗?有,Total表里有C/DemoC/CCC。分店有CCC吗?有,Shop表里有DemoB/CCC。因此Matched,且P.DName(DemoC) != S.DName(DemoB),所以更新Total表的C名为DemoB。
- DemoF (FFF): 总表无,触发插入。
- DemoD, DemoE: 总表有,分店无,不触发删除,保留。
因此,总表最终包含:AAA(不变), B(原BBB不变), C(改名DemoB), D(不变), E(不变), F(新增)。
监控Merge语句的影响
在执行Merge时,了解受影响的行数和具体变更详情非常重要。
第5步:获取影响行数
可以使用系统变量获取本次Merge影响的总行数:
@@ROWCOUNT:返回int类型影响行数。ROWCOUNT_BIG():返回bigint类型,适用于超过20亿行的超大操作。
第6步:输出详细变更日志
使用OUTPUT子句可以将Deleted(旧值)、Inserted(新值)或两者存入临时表或表变量中,便于审计。
-- 定义表变量存储输出日志
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;
-- 查询影响总数
select @@ROWCOUNT as Count1, ROWCOUNT_BIG() as Count2
-- 查看被删除的记录详情
select * from @tableVarRecord;
结果说明: @tableVarRecord中将包含所有被Delete操作清除的行详情(即分店表里没有的总表记录)。这在需要撤销操作或生成报表时非常有用。
总结
Merge语句是SQL Server 2008及更高版本中处理“Upsert”(更新或插入)操作的利器,它能显著减少网络往返次数和锁竞争,提高数据同步效率。通过合理组合Matched、Not Matched By Target和Not Matched By Source三种状态,您可以灵活控制数据的同步策略,并利用Output子句确保数据变更的可追溯性。
以上就是SQL Server 2008中Merge语句用法的详细内容,更多关于SQL Server数据同步的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













