MERGE is “apply this incoming set to that table.” For each source row, DB2 for z/OS tests an ON condition against the target. When it matches, you UPDATE or DELETE. When it does not, you INSERT. One statement replaces a brittle pair of UPDATE-then-INSERT programs, as long as you respect z/OS source rules and MERGE restrictions.
IBM’s picture is a right join of the target to the source using ON. Where that join is true, the MATCHED action runs. Where it is not true, the NOT MATCHED insert runs. Matching conditions are evaluated in the order you write them; once a row satisfies a WHEN (when NOT ATOMIC is not used), later WHEN clauses do not see it again.
12345678MERGE INTO RECORDS AR USING (SELECT ACTIVITY, DESCRIPTION FROM ACTIVITIES) AC ON (AR.ACTIVITY = AC.ACTIVITY) WHEN MATCHED THEN UPDATE SET DESCRIPTION = AC.DESCRIPTION WHEN NOT MATCHED THEN INSERT (ACTIVITY, DESCRIPTION) VALUES (AC.ACTIVITY, AC.DESCRIPTION);
That IBM example updates descriptions that already exist and inserts activities that do not. Correlation names AR and AC keep column names unambiguous. Qualify every key in ON when the same name exists on both sides.
| Source | Example shape | Notes |
|---|---|---|
| Table-reference | USING (SELECT … FROM ACTIVITIES) AS AC | No NOT ATOMIC; empty source returns a warning |
| Single-row VALUES | USING (VALUES ('rsk', 3)) AS T(ID, AMT) | One source row of constants or host variables |
| Multiple-row VALUES | VALUES … FOR :N ROWS | Requires NOT ATOMIC CONTINUE ON SQLEXCEPTION; max 750 values |
A table-reference can be a base table, a view, or a nested fullselect. If that result is empty, Db2 returns a warning and changes nothing. Do not specify NOT ATOMIC with a table-reference. Do not mix table-reference and VALUES in the same MERGE.
1234567MERGE INTO T1 AS A USING TABLE (VALUES ('rsk', 3)) AS T (ID, AMOUNT) ON A.COL1 = T.ID WHEN MATCHED THEN UPDATE SET COL2 = T.AMOUNT WHEN NOT MATCHED THEN INSERT (COL1, COL2) VALUES (T.ID, T.AMOUNT);
Multiple-row VALUES and host-variable arrays are the embedded-SQL path for a batch of incoming rows. FOR n ROWS says how many array slots to merge (1–32767). The number of VALUES items must not exceed 750. Expressions in VALUES must not be column names of the target and must not use NEXT VALUE / PREVIOUS VALUE.
ON is the match rule. Each column name must belong to the target or the source. Subqueries are not allowed in ON. IN and quantified predicates must not include a fullselect. Aggregate functions and non-deterministic scalar functions are also out. Keep ON as an equality (or a small AND of equalities) on keys.
WHEN MATCHED AND extra-condition lets you split matches: for example UPDATE when status is active, DELETE when status is cancelled. WHEN NOT MATCHED AND extra- condition filters inserts; that extra condition must not reference target columns.
1234567891011MERGE INTO HR.EMPLOYEE E USING HR.EMP_INBOUND I ON E.EMPNO = I.EMPNO WHEN MATCHED AND I.ACTION = 'UPD' THEN UPDATE SET SALARY = I.SALARY, BONUS = I.BONUS WHEN MATCHED AND I.ACTION = 'DEL' THEN DELETE WHEN NOT MATCHED AND I.ACTION = 'ADD' THEN INSERT (EMPNO, LASTNAME, SALARY, BONUS) VALUES (I.EMPNO, I.LASTNAME, I.SALARY, I.BONUS);
WHEN MATCHED THEN UPDATE SET looks like searched UPDATE assignment: expressions, DEFAULT, NULL, or a row-fullselect. Expressions can read target and source columns; the target column value is the value before this row is updated. Do not assign generated ALWAYS columns except DEFAULT. The same target column must not appear twice in one SET. With VALUES sources, later source rows can update a row already updated earlier in the same MERGE (cumulative).
WHEN NOT MATCHED THEN INSERT lists columns and VALUES from the source. Omitted columns get defaults (or null). GENERATED ALWAYS columns should receive DEFAULT. INSERT must not reference a column of the target table—the row does not exist yet. Views that are not insertable need an explicit column list that skips non-updatable columns.
WHEN MATCHED THEN DELETE removes the matching target row. RI, delete triggers, and temporal history behavior are those of DELETE. Use DELETE in MERGE when the source is a “cancel this key” feed rather than running a separate DELETE first.
| Clause | Meaning |
|---|---|
| WHEN MATCHED THEN UPDATE | ON is true: change target columns from source (or expressions) |
| WHEN MATCHED THEN DELETE | ON is true: remove the matching target row |
| WHEN NOT MATCHED THEN INSERT | No match: insert a new target row from source values |
| WHEN … AND extra THEN SIGNAL | Abort that row (or statement, depending on atomicity) with SQLSTATE |
MERGE is not a replacement for LOAD or for unconstrained mass UPDATE. It shines when a modest source set must be applied to a keyed target with mixed insert/update/delete outcomes in one atomic (or NOT ATOMIC) statement.
You have a binder of class records (the target) and a pile of new slips (the source). For each slip, you look up the student number. If the student is already in the binder, you erase and rewrite the line (UPDATE) or pull the page out (DELETE). If the number is new, you add a page (INSERT). ON is “same student number.” MATCHED means you found them. NOT MATCHED means you did not.
1. What does WHEN MATCHED mean in MERGE?
2. What does WHEN NOT MATCHED allow after THEN?
3. Can the ON clause of MERGE contain a subquery?
4. When must you specify NOT ATOMIC CONTINUE ON SQLEXCEPTION?
5. What is MERGE logically like?