MERGE Statement
The MERGE
statement is a powerful T-SQL construct that allows you to perform conditional INSERT
, UPDATE
, or DELETE
operations on a target table based on the results of joining it with a source table. It's often referred to as an "upsert" operation (update or insert).
Syntax
MERGE target_table AS T
USING source_table AS S
ON T.merge_column = S.merge_column
WHEN MATCHED THEN
UPDATE SET
T.column1 = S.column1,
T.column2 = S.column2
WHEN NOT MATCHED BY TARGET THEN
INSERT (column1, column2, column3)
VALUES (S.column1, S.column2, S.column3)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
Key Components
MERGE target_table AS T
: Specifies the table that will be modified.USING source_table AS S
: Specifies the table or query that provides the data for comparison and operations.ON T.merge_column = S.merge_column
: Defines the join condition used to match rows between the target and source.WHEN MATCHED THEN ...
: Specifies actions to take when a row from the source finds a matching row in the target based on theON
condition. This can includeUPDATE
orDELETE
.WHEN NOT MATCHED BY TARGET THEN ...
: Specifies actions to take when a row from the source does not have a matching row in the target. Typically used forINSERT
.WHEN NOT MATCHED BY SOURCE THEN ...
: Specifies actions to take when a row in the target does not have a matching row in the source. This is used forDELETE
operations (to remove rows from the target that are no longer present in the source). This clause is optional.
When to Use MERGE
- Synchronizing data between two tables.
- Loading data from staging tables into production tables where records might exist or need to be added.
- Implementing complex conditional updates based on source data.
Example: Synchronizing Product Inventory
Let's say we have a Products
table (target) and a StagingProducts
table (source). We want to update existing products or insert new ones.
-- Target table
CREATE TABLE Products (
ProductID INT PRIMARY KEY,
ProductName VARCHAR(100),
Stock INT
);
-- Source table (e.g., data from an external feed)
CREATE TABLE StagingProducts (
ProductID INT PRIMARY KEY,
ProductName VARCHAR(100),
NewStock INT
);
-- Populate with some sample data
INSERT INTO Products (ProductID, ProductName, Stock) VALUES
(1, 'Laptop', 50),
(2, 'Keyboard', 100);
INSERT INTO StagingProducts (ProductID, ProductName, NewStock) VALUES
(1, 'Laptop Pro', 45), -- Update existing
(3, 'Mouse', 200); -- Insert new
-- MERGE statement to synchronize
MERGE Products AS T
USING StagingProducts AS S
ON T.ProductID = S.ProductID
WHEN MATCHED THEN
UPDATE SET
T.ProductName = S.ProductName,
T.Stock = S.NewStock
WHEN NOT MATCHED BY TARGET THEN
INSERT (ProductID, ProductName, Stock)
VALUES (S.ProductID, S.ProductName, S.NewStock);
-- After the MERGE, the Products table will be:
-- ProductID | ProductName | Stock
-- -----------|--------------|-------
-- 1 | Laptop Pro | 45
-- 2 | Keyboard | 100
-- 3 | Mouse | 200
Example: Deleting Old Records
If a product is removed from the source (StagingProducts
), we might want to delete it from the target (Products
).
-- Assume StagingProducts no longer contains ProductID 2
DELETE FROM StagingProducts WHERE ProductID = 2;
MERGE Products AS T
USING StagingProducts AS S
ON T.ProductID = S.ProductID
WHEN MATCHED THEN
UPDATE SET
T.ProductName = S.ProductName,
T.Stock = S.NewStock
WHEN NOT MATCHED BY TARGET THEN
INSERT (ProductID, ProductName, Stock)
VALUES (S.ProductID, S.ProductName, S.NewStock)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
-- After this MERGE, ProductID 2 will be deleted from Products
Considerations
- The
MERGE
statement must include at least oneWHEN MATCHED
orWHEN NOT MATCHED BY TARGET
clause. - If
WHEN NOT MATCHED BY SOURCE
is used, it should be the last clause. - Performance can be sensitive to the join condition and indexing on both tables.
- Multiple
WHEN MATCHED
clauses are not allowed. - Use output clauses (
$action
) to track changes made by the MERGE statement.