MERGE
Purpose
Use this statement to merge rows from a source into a target table. The source can be a table or a query.
The rows returned by the source determine which rows in the target table will be updated, deleted, or inserted. Therefore, the MERGE statement unites these three statements - UPDATE, DELETE, and INSERT.
The source can contain data for new customers, customers to be dropped, or changes to existing customers. It can be a table or a query. The MERGE statement can use this data to insert new customers into the target table, delete non-valid customers, and update existing customers.
Prerequisites
-
You need either the system privilege
USE ANY SCHEMAor the object privilegeUSAGEon the target schema, or the schema must be owned by you or one of your assigned roles. - You need to have the appropriate
INSERT,DELETE, andUPDATEprivileges on the target table. - You need to have the appropriate
SELECTprivileges on the update table.
Syntax
merge::=
merge_update_clause::=
merge_delete_clause::=
merge_insert_clause::=
Usage notes
- The
ONcondition describes the correlation between the two tables (similar to a join). TheMATCHEDclause is used for matching row pairs, and theNOT MATCHEDclause is used for those that do not match. In theONcondition, only equivalence conditions (=) are permitted. - In the
UPDATEclause, the optionalWHEREcondition specifies the circumstances under which theUPDATEis conducted, whereby it is permissible for both the target table and the update table to be referenced for this. With the support of the optionalDELETEcondition, it is possible to delete rows in the target table. Only the rows that have been matched by theWHEREclause of theUPDATEare taken into consideration for theDELETEclause. TheWHEREclause of theDELETEstatement uses the values after theUPDATE. - In the
DELETEclause, the optionalWHEREcondition specifies the circumstances under which theDELETEis performed. - In the
INSERTclause, the optionalWHEREcondition specifies the circumstances under which theINSERTis performed. It is permissible to reference columns of the update table in theINSERTclause. - The
UPDATE,DELETE, andINSERTclauses are optional with the restriction that at least one must be specified. The order of these clauses is interchangeable. - The
INSERTandUPDATEclauses treat the default values and identity columns in the same way as in theINSERTandUPDATEstatements. However, the only exception is thatINSERT DEFAULT VALUESis not allowed. - If there are several entries in the update table that could apply to an
UPDATEof a single row in the target table, then this displays the error message "Unable to get a stable set of rows in the source tables", if theUPDATEcandidates would change the original value of the target table. - If several entries in the update table could apply to a
DELETEof a single row in the target table, this displays the error message "Unable to get a stable set of rows in the source tables".
Examples
Consider the following sample tables and examples statements based on these tables:
Staff
| name | salary | lastchange |
|---|---|---|
| meier | 30000 | 2006-01-01 |
| schmidt | 40000 | 2006-05-01 |
| mueller | 50000 | 2005-08-01 |
Changes
| name | salary |
|---|---|
| schmidt | 43000 |
| hofman | 35000 |
| meier | 29000 |
Deletes
| name |
|---|
| meier |
-- Merging the table updates
MERGE INTO staff T
USING changes U
ON T.name = U.name
WHEN MATCHED THEN UPDATE SET T.salary = U.salary,
T.lastChange = CURRENT_DATE
WHERE T.salary < U.salary
WHEN NOT MATCHED THEN INSERT VALUES (U.name,U.salary,CURRENT_DATE);
SELECT * FROM staff;
Results
| name | salary | lastchange |
|---|---|---|
| meier | 30000 | 2006-01-01 |
| schmidt | 43000 | 2010-10-06 |
| mueller | 50000 | 2005-08-01 |
| hofmann | 35000 | 2010-10-06 |
-- Merging the table deletes
MERGE INTO staff T
USING deletes U
ON T.name = U.name
WHEN MATCHED THEN DELETE;
SELECT * FROM staff;
Results
| name | salary | lastchange |
|---|---|---|
| hofmann | 35000 | 2010-10-06 |
| schmidt | 43000 | 2010-10-06 |
| mueller | 50000 | 2005-08-01 |
Upserting a single row
You can also use MERGE to insert a row if it does not exist, or update it if it already exists. This is often called an upsert. The USING clause can contain a query that supplies the values for one row; a separate source table is not required.
The following example assumes that the customer table has the columns customer_id, name, and email:
MERGE INTO customer AS target
USING (
SELECT
42 AS customer_id,
'John Doe' AS name,
'johndoe@example.com' AS email
) AS src
ON target.customer_id = src.customer_id
WHEN MATCHED THEN
UPDATE SET
target.name = src.name,
target.email = src.email
WHEN NOT MATCHED THEN
INSERT (customer_id, name, email)
VALUES (src.customer_id, src.name, src.email);
The ON condition checks whether a row with customer_id 42 exists in customer. If it exists, MERGE updates its name and email. If it does not exist, MERGE inserts a new row.