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;
?