![]() |
|
|
By: Arshad Ali | Read Comments (4) | Print Arshad is a SQL and BI Developer focusing on Data Warehousing projects @ Microsoft India R&D Pvt Ltd. Related Tips: More |
|
Solution
Beginning with SQL Server 2008, now you can use MERGE SQL command to perform these operations in a single statement. This new command is similar to the UPSERT (fusion of the words UPDATE and INSERT.) command of Oracle; it inserts rows that don’t exist and updates the rows that do exist. With the introduction of the MERGE SQL command, developers can more effectively handle common data warehousing scenarios, like checking whether a row exists, and then executing an insert or update or delete.
The MERGE statement basically merges data from a source result set to a target table based on a condition that you specify and if the data from the source already exists in the target or not. The new SQL command combines the sequence of conditional INSERT, UPDATE and DELETE commands in a single atomic statement, depending on the existence of a record. The new MERGE SQL command looks like as below:
MERGE <target_table> [AS TARGET] USING <table_source> [AS SOURCE] ON <search_condition> [WHEN MATCHED THEN <merge_matched> ] [WHEN NOT MATCHED [BY TARGET] THEN <merge_not_matched> ] [WHEN NOT MATCHED BY SOURCE THEN <merge_ matched> ]; |
The MERGE statement basically works as separate insert, update, and delete statements all within the same statement. You specify a "Source" record set and a "Target" table, and the join between the two. You then specify the type of data modification that is to occur when the records between the two data are matched or are not matched. MERGE is very useful, especially when it comes to loading data warehouse tables, which can be very large and require specific actions to be taken when rows are or are not present.
Putting it all together
In this example I will take a Products table as target table and UpdatedProducts as a source table containing updated list of products. I will then use the MERGE SQL command to synchronize the target table with the source table.
First Let's create a target table and a source table and populate some data to these tables.
|
MERGE SQL statement - Part 1 |
--Create a target table CREATE TABLE Products ( ProductID INT PRIMARY KEY, ProductName VARCHAR(100), Rate MONEY ) GO --Insert records into target table INSERT INTO Products VALUES (1, 'Tea', 10.00), (2, 'Coffee', 20.00), (3, 'Muffin', 30.00), (4, 'Biscuit', 40.00) GO --Create source table CREATE TABLE UpdatedProducts ( ProductID INT PRIMARY KEY, ProductName VARCHAR(100), Rate MONEY ) GO --Insert records into source table INSERT INTO UpdatedProducts VALUES (1, 'Tea', 10.00), (2, 'Coffee', 25.00), (3, 'Muffin', 35.00), (5, 'Pizza', 60.00) GO SELECT * FROM Products SELECT * FROM UpdatedProducts GO |
Next I will use the MERGE SQL command to synchronize the target table with the refreshed data coming from the source table.
|
MERGE SQL statement - Part 2 |
--Synchronize the target table with --refreshed data from source table MERGE Products AS TARGET USING UpdatedProducts AS SOURCE ON (TARGET.ProductID = SOURCE.ProductID) --When records are matched, update --the records if there is any change WHEN MATCHED AND TARGET.ProductName <> SOURCE.ProductName OR TARGET.Rate <> SOURCE.Rate THEN UPDATE SET TARGET.ProductName = SOURCE.ProductName, TARGET.Rate = SOURCE.Rate --When no records are matched, insert --the incoming records from source --table to target table WHEN NOT MATCHED BY TARGET THEN INSERT (ProductID, ProductName, Rate) VALUES (SOURCE.ProductID, SOURCE.ProductName, SOURCE.Rate) --When there is a row that exists in target table and --same record does not exist in source table --then delete this record from target table WHEN NOT MATCHED BY SOURCE THEN DELETE --$action specifies a column of type nvarchar(10) --in the OUTPUT clause that returns one of three --values for each row: 'INSERT', 'UPDATE', or 'DELETE', --according to the action that was performed on that row OUTPUT $action, DELETED.ProductID AS TargetProductID, DELETED.ProductName AS TargetProductName, DELETED.Rate AS TargetRate, INSERTED.ProductID AS SourceProductID, INSERTED.ProductName AS SourceProductName, INSERTED.Rate AS SourceRate; SELECT @@ROWCOUNT; GO |
When the above is run this is the output. There were 2 updates, 1 delete and 1 insert.

If we select all records from the Products table we can see the final results. We can see the Coffee rate was updated from 20.00 to 25.00, the Muffin rate was updated from 30.00 to 35.00, Biscuit was deleted and Pizza was inserted.

Notes
Next Steps
| Share: | Share | Tweet |
|
![]() |
![]() |
Free SQL Server Learning |
| Wednesday, March 11, 2009 - 1:33:23 PM - arshad0384 |
|
|
First of all thanks for your appreciation and thanks again for addition, this will help the readers. |
|
| Tuesday, September 28, 2010 - 1:46:27 PM - kv |
|
|
How do we use the merge function when the source and target are on different databases? |
|
| Thursday, March 10, 2011 - 5:09:03 PM - Don |
|
|
Best example and explanation of a multi-matched/not matched merge I have encountered. Well Done! |
|
|
privacy | disclaimer | copyright | advertise | about authors | contribute | feedback | giveaways | user groups Some names and products listed are the registered trademarks of their respective owners. Edgewood Solutions LLC | MSSharePointTips.com | MSSQLTips.com |