标签:
TSQL的Merge语句不仅能够同步数据,而且能够将更新的数据输出。
一,语法
1,when match子句要求Target表中一个数据行只能被更新一次
If UPDATE is specified in the <merge_matched> clause, and more than one row of <table_source>matches a row in target_table based on <merge_search_condition>, SQL Server returns an error. The MERGE statement cannot update the same row more than once, or update and delete the same row.
如果Target表中一个数据行只能被更新一次,sql Server会报错,错误原因是Source Table的中多行数据和Target Table中一行数据匹配。
Msg 8672, Level 16, State 1, Line 3
The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.
2,Output子句将Target Table中更新的数据输出
<OUTPUT_CLAUSE> ::=
{
[ OUTPUT <dml_select_list> INTO { @table_variable | output_table } [ ( column_list ) ] ]
[ OUTPUT <dml_select_list> ]
}
<dml_select_list> ::= { <column_name> | scalar_expression } [ [AS] column_alias_identifier ] [ ,...n ]
<column_name> ::= { DELETED | INSERTED | from_table_name } . { * | column_name } | $action
Output Clause returns a row for every row in target_table that is updated, inserted, or deleted, in no particular order. $action can be specified in the output clause. $action is a column of type nvarchar(10) that returns one of three values for each row: ‘INSERT‘, ‘UPDATE‘, or ‘DELETE‘, according to the action that was performed on that row
表Deleted和Inserted 是特殊的两个系统表,由系统创建,并且用户语句只能读取,不能修改,作用域是语句级别,当语句结束时,系统自动回收。
DELETED
Is a column prefix that specifies the value deleted by the update or delete operation. Columns prefixed with DELETED reflect the value before the UPDATE, DELETE, or MERGE statement is completed.
DELETED cannot be used with the OUTPUT clause in the INSERT statement.
INSERTED
Is a column prefix that specifies the value added by the insert or update operation. Columns prefixed with INSERTED reflect the value after the UPDATE, INSERT, or MERGE statement is completed but before triggers are executed.
INSERTED cannot be used with the OUTPUT clause in the DELETE statement.
二,示例
1,创建示例表和数据
use tempdb create table dbo.tar ( id int, name varchar(11) ) create table dbo.src ( id int, name varchar(11) ) insert into dbo.tar values(1,‘t1‘),(2,‘t2‘),(3,‘t3‘) insert into dbo.src(id,name) values(1,‘t1‘),(2,‘s2‘),(4,‘s4‘)
2,同步数据
merge into dbo.tar as t using dbo.src as s on t.id=s.id --matched表示On子句匹配成功,加上额外的and条件,如果when子句成功,那么更新Targe表中的数据 when matched and t.name<>s.name then update set t.name=s.name --not matched表示On子句不匹配 --ID不存在于Targe表,存在于Source表,则将行插入到Targe表 when not matched --default by target then insert (id,name) values(s.id,s.name) --ID存在于Targe表,而不存在于Source表,那么将行从Target表删除 when not matched by source then delete;
2,将Target Table中更新的数据输出
merge into dbo.tar as t using dbo.src as s on t.id=s.id --matched表示On子句匹配成功,加上额外的and条件,如果when子句成功,那么更新Targe表中的数据 when matched and t.name<>s.name then update set t.name=s.name --not matched表示On子句不匹配 --ID不存在于Targe表,存在于Source表,则将行插入到Targe表 when not matched --default by target then insert (id,name) values(s.id,s.name) --ID存在于Targe表,而不存在于Source表,那么将行从Target表删除 when not matched by source then delete output $action,deleted.id as Deleted_ID,deleted.name as Deleted_Name,inserted.id as Instered_ID,inserted.name as Instered_Name ;
3,将Targe Table中更新的数据插入到一个表中有两种方式,一种是output into,一种是使用insert into
Output Into
create table dbo.dt_merge_output ( action nvarchar(10), Deleted_ID int, Deleted_Name nvarchar(11), Inserted_ID int, Inserted_Name nvarchar(11) ) merge into dbo.tar as t using dbo.src as s on t.id=s.id --matched表示On子句匹配成功,加上额外的and条件,如果when子句成功,那么更新Targe表中的数据 when matched and t.name<>s.name then update set t.name=s.name --not matched表示On子句不匹配 --ID不存在于Targe表,存在于Source表,则将行插入到Targe表 when not matched --default by target then insert (id,name) values(s.id,s.name) --ID存在于Targe表,而不存在于Source表,那么将行从Target表删除 when not matched by source then delete output $action,deleted.id as Deleted_ID,deleted.name as Deleted_Name,inserted.id as Instered_ID,inserted.name as Instered_Name into dbo.dt_merge_output ; select * from dbo.dt_merge_output
Insert Into
create table dbo.dt_merge_output ( action nvarchar(10), Deleted_ID int, Deleted_Name nvarchar(11), Inserted_ID int, Inserted_Name nvarchar(11) ) insert into dbo.dt_merge_output select * from ( merge into dbo.tar as t using dbo.src as s on t.id=s.id --matched表示On子句匹配成功,加上额外的and条件,如果when子句成功,那么更新Targe表中的数据 when matched and t.name<>s.name then update set t.name=s.name --not matched表示On子句不匹配 --ID不存在于Targe表,存在于Source表,则将行插入到Targe表 when not matched --default by target then insert (id,name) values(s.id,s.name) --ID存在于Targe表,而不存在于Source表,那么将行从Target表删除 when not matched by source then delete output $action,deleted.id as Deleted_ID,deleted.name as Deleted_Name,inserted.id as Instered_ID,inserted.name as Instered_Name ) as p(Action,Deleted_ID,Deleted_Name,Instered_ID,Instered_Name)
4,Using MERGE to perform UPDATE and INSERT operations on a target table by using a derived source table
在using子句中使用(Vaules(),()....) as Source(Column_Name_list)来创建一个Derived Table作为Source。
MERGE INTO Sales.SalesReason AS Target USING (VALUES (‘Recommendation‘,‘Other‘), (‘Review‘, ‘Marketing‘), (‘Internet‘, ‘Promotion‘)) AS Source (NewName, NewReasonType) ON Target.Name = Source.NewName WHEN MATCHED THEN UPDATE SET ReasonType = Source.NewReasonType WHEN NOT MATCHED BY TARGET THEN INSERT (Name, ReasonType) VALUES (NewName, NewReasonType) OUTPUT $action;
参考MSDN
Merge:
https://msdn.microsoft.com/en-us/library/bb510625%28v=sql.110%29.aspx?f=255&MSPPError=-2147217396
OUTPUT Clause
https://msdn.microsoft.com/de-de/library/ms177564%28v=sql.110%29.aspx?f=255&MSPPError=-2147217396
标签:
原文地址:http://www.cnblogs.com/ljhdo/p/4816458.html