Example 1
Apply updates and deletions from a staging table in one pass
The source table has three rows. Row id=1 matches a target row and remove=0, so the second WHEN MATCHED clause fires and updates the name to 'Widget Pro' and price to 15. Row id=2 also matches and remove=1, so the first WHEN MATCHED AND s.remove clause fires and deletes the target row. Row id=3 has no match in products, so WHEN NOT MATCHED fires and inserts it. The final SELECT shows two rows: the updated Widget Pro and the newly inserted Doohickey. SQL Server uses WHEN NOT MATCHED BY TARGET to distinguish source rows with no target match from WHEN NOT MATCHED BY SOURCE (target rows with no source match). PostgreSQL uses the simpler WHEN NOT MATCHED. In both engines the WHEN clauses fire in order and only the first matching one applies.
CREATE TABLE products (id INT PRIMARY KEY, name VARCHAR(50), price INT);
CREATE TABLE product_updates (id INT, name VARCHAR(50), price INT, remove BIT);
INSERT INTO
products
VALUES
(1, 'Widget', 10),
(2, 'Gadget', 20);
INSERT INTO
product_updates
VALUES
(1, 'Widget Pro', 15, 0),
(2, 'Gadget', 20, 1),
(3, 'Doohickey', 8, 0);MERGE products AS t USING product_updates AS s ON t.id = s.id WHEN MATCHED
AND s.remove = 1 THEN DELETE WHEN MATCHED THEN
UPDATE
SET
t.name = s.name,
t.price = s.price WHEN NOT MATCHED BY TARGET THEN INSERT (id, name, price)
VALUES
(s.id, s.name, s.price);
SELECT
id,
name,
price
FROM
products
ORDER BY
id;| id | name | price |
|---|---|---|
| 1 | Widget Pro | 15 |
| 3 | Doohickey | 8 |
CREATE TABLE products (id INT PRIMARY KEY, name VARCHAR(50), price INT);
CREATE TABLE product_updates (
id INT,
name VARCHAR(50),
price INT,
remove BOOLEAN
);
INSERT INTO
products
VALUES
(1, 'Widget', 10),
(2, 'Gadget', 20);
INSERT INTO
product_updates
VALUES
(1, 'Widget Pro', 15, FALSE),
(2, 'Gadget', 20, TRUE),
(3, 'Doohickey', 8, FALSE);MERGE INTO products AS t USING product_updates AS s ON t.id = s.id WHEN MATCHED
AND s.remove THEN DELETE WHEN MATCHED THEN
UPDATE
SET
name = s.name,
price = s.price WHEN NOT MATCHED THEN INSERT (id, name, price)
VALUES
(s.id, s.name, s.price);
SELECT
id,
name,
price
FROM
products
ORDER BY
id;| id | name | price |
|---|---|---|
| 1 | Widget Pro | 15 |
| 3 | Doohickey | 8 |
SQL Server and PostgreSQL 15+ support MERGE with slightly different clause syntax. MySQL, MariaDB, and SQLite have no equivalent.