-- Both clauses present. MERGEINTO test1 a USING all_objects b ON (a.object_id = b.object_id) WHEN MATCHED THEN UPDATE SET a.status = b.status WHENNOT MATCHED THEN INSERT (object_id, status) VALUES (b.object_id, b.status);
-- No matched clause, insert only. MERGEINTO test1 a USING all_objects b ON (a.object_id = b.object_id) WHENNOT MATCHED THEN INSERT (object_id, status) VALUES (b.object_id, b.status);
-- No not-matched clause, update only. MERGEINTO test1 a USING all_objects b ON (a.object_id = b.object_id) WHEN MATCHED THEN UPDATE SET a.status = b.status;
-- Both clauses present. MERGEINTO test1 a USING all_objects b ON (a.object_id = b.object_id) WHEN MATCHED THEN UPDATE SET a.status = b.status WHERE b.status !='VALID' WHENNOT MATCHED THEN INSERT (object_id, status) VALUES (b.object_id, b.status) WHERE b.status !='VALID';
-- No matched clause, insert only. MERGEINTO test1 a USING all_objects b ON (a.object_id = b.object_id) WHENNOT MATCHED THEN INSERT (object_id, status) VALUES (b.object_id, b.status) WHERE b.status !='VALID';
-- No not-matched clause, update only. MERGEINTO test1 a USING all_objects b ON (a.object_id = b.object_id) WHEN MATCHED THEN UPDATE SET a.status = b.status WHERE b.status !='VALID';
An optional DELETE WHERE clause can be added to the MATCHED clause to clean up after a merge operation. Only those rows in the destination table that match both the ON clause and the DELETE WHERE are deleted. If you add a WHERE clause to the update in the matched clause, we can think of this as additional match criteria for the delete, as only rows that are touched by the update are available for the DELETE clause to remove. Depending on which table the DELETE WHERE references, it can target the rows prior or post update. The following examples clarify this.
CREATETABLE source AS SELECT level AS id, CASE WHENMOD(level, 2) =0THEN10 ELSE20 ENDAS status, 'Description of level '|| level AS description FROM dual CONNECTBY level <=5;
SELECT*FROM source;
ID STATUS DESCRIPTION ---------- ---------- ----------------------- 120 Description of level 1 210 Description of level 2 320 Description of level 3 410 Description of level 4 520 Description of level 5
5rows selected.
SQL>
Create the destination table using a similar query, but this time with 10 rows.
CREATETABLE destination AS SELECT level AS id, CASE WHENMOD(level, 2) =0THEN10 ELSE20 ENDAS status, 'Description of level '|| level AS description FROM dual CONNECTBY level <=10;
SELECT*FROM destination;
120 Description of level 1 210 Description of level 2 320 Description of level 3 410 Description of level 4 520 Description of level 5 610 Description of level 6 720 Description of level 7 810 Description of level 8 920 Description of level 9 1010 Description of level 10
10rows selected.
SQL>
The following MERGE statement will update all the rows in the destination table that have a matching row in the source table. The additional DELETE WHERE clause will delete only those rows that were matched, already in the destination table, and meet the criteria of the DELETE WHERE clause.
MERGEINTO destination d USING source s ON (s.id = d.id) WHEN MATCHED THEN UPDATE SET d.description ='Updated' DELETEWHERE d.status =10;
5rows merged.
SQL>
SELECT*FROM destination;
ID STATUS DESCRIPTION ---------- ---------- ----------------------- 120 Updated 320 Updated 520 Updated 610 Description of level 6 720 Description of level 7 810 Description of level 8 920 Description of level 9 1010 Description of level 10
8rows selected.
SQL>
Notice there are rows with a status of “10” that were not deleted. This is because there was no match between the source and destination for these rows, so the delete was not applicable.
The following example shows the DELETE WHERE can be made to match against values of the rows before the update operation, not after. In this case, all matching rows have their status changed to “10”, but the DELETE WHERE references the source data, so the status is checked against the source, not the updated values.
MERGEINTO destination d USING source s ON (s.id = d.id) WHEN MATCHED THEN UPDATE SET d.description ='Updated', d.status =10 DELETEWHERE d.status =10;
5rows merged.
SQL>
SELECT*FROM destination;
ID STATUS DESCRIPTION ---------- ---------- ----------------------- 610 Description of level 6 720 Description of level 7 810 Description of level 8 920 Description of level 9 1010 Description of level 10