SQL Clone
SQLServerCentral is supported by Redgate
Log in  ::  Register  ::  Not logged in

The MERGE statement in SQL Server

The SQL MERGE statement was introduced in SQL Server 2008 and allows you to modify data in a target table based on data in a source table in one easy statement, replacing lots of messy code.  I use it frequently when building a data warehouse.

In short, the statement joins the target to the source by using a column common to both tables, such as a primary key.  You can then insert, modify, or delete data from the target table—all in one statement—according to how the rows match up as a result of the join.

I highly recommend becoming familiar with the MERGE statement as you will find yourself using it frequently.

Here is an example use of the MERGE statement:

MERGE [MD-Cache].[GRD].[TblContinent] AS target
USING (SELECT SlbMasterData_PK, Name, SourceID, ContinentCode, GRDStatus, ModifiedBy, ModifiedDate FROM [MDS2012].[mdm].[vGRD_TblContinent])
		AS source (SlbMasterData_PK, Name, SourceID, ContinentCode, GRDStatus, ModifiedBy, ModifiedDate)
ON (target.SlbMasterData_PK = source.SlbMasterData_PK)
--record is in source as well as target, only update in target if a field has changed or status in target is "DEPRECATED"
WHEN MATCHED AND (target.Name <> source.Name OR target.SourceID <> source.SourceID OR target.Code <> source.ContinentCode OR target.GRDStatus <> source.GRDStatus
					OR target.ModifiedBy <> source.ModifiedBy OR target.ModifiedDate <> source.ModifiedDate OR target.MasterDataStatus_FK = 'DEPRECATED') THEN
	SET target.Name = source.Name, target.SourceID = source.SourceID, target.Code = source.ContinentCode,
			target.GRDStatus = source.GRDStatus, target.ModifiedBy = source.ModifiedBy, target.ModifiedDate = source.ModifiedDate, target.MasterDataStatus_FK='ACTIVE'
--record is in source but not target, so insert into target
	INSERT (Name, SourceID, Code, SlbMasterData_PK, MasterDataStatus_FK, GRDStatus, ModifiedBy, ModifiedDate)
		VALUES (source.Name, source.SourceID, source.ContinentCode, source.SlbMasterData_PK, 'ACTIVE', 'APPROVED', 'Org-by', getdate())
--record has been deleted from source...don't delete it in target but rather mark the status in target as "DEPRECATED" (if it is not already)
	set target.MasterDataStatus_FK = 'DEPRECATED'
--display results of MERGE
OUTPUT $action, Deleted.SlbMasterData_PK, Inserted.SlbMasterData_PK, Deleted.SourceID, Inserted.SourceID, Deleted.Code, Inserted.Code,
	Deleted.GRDStatus, Inserted.GRDStatus, Deleted.MasterDataStatus_FK, Inserted.MasterDataStatus_FK, Deleted.ModifiedDate, Inserted.ModifiedDate, Deleted.ModifiedBy, Inserted.ModifiedBy;

More info:

MERGE Statement Generator

MERGE gives better OUTPUT options

What is the T-SQL Merge Statement and How do you use it?

The MERGE Statement in SQL Server 2008

Be Careful with the Merge Statement

Optimizing MERGE Statement Performance

James Serra's Blog

James is a big data and data warehousing technology specialist at Microsoft. He is a thought leader in the use and application of Big Data technologies, including MPP solutions involving hybrid technologies of relational data, Hadoop, and private and public cloud. Previously he was an independent consultant working as a Data Warehouse/Business Intelligence architect and developer. He is a prior SQL Server MVP with over 30 years of IT experience. James is a popular blogger (JamesSerra.com) and speaker, having presented at dozens of PASS events including the PASS Business Analytics conference and the PASS Summit. He is the author of the book “Reporting with Microsoft SQL Server 2012”. He received a Bachelor of Science degree in Computer Engineering from the University of Nevada-Las Vegas.


Leave a comment on the original post [www.jamesserra.com, opens in a new window]

Loading comments...