MERGE Statement
Standard Anwendung
Eine (relativ) kleine Update-Tabelle wird benutzt, um Änderungen in eine (relativ) große Fakt-Tabelle zu übernehmen. Dabei sollen existierende Einträge (Primärschlüssel) aktualisiert und neue Einträge eingefügt werden.
-
MERGE INTO customers c USING new_customers n ON (n.customer_no = c.customer_no) WHEN MATCHED THEN UPDATE SET city_id=n.city_id WHEN NOT MATCHED THEN INSERT VALUES (customer_no, first_name, last_name, gender, birthday, city_id);
Merge, reversed scenario
Beim "reversed" Merge geht es in der Regel nicht darum, Daten zu übernehmen, sondern eher um das Markieren von Zeilen nach gewissen Kriterien, z.B. im Zuge von Primary- und Foreign-Key Prüfungen während des ETL-Prozesses. Dementsprechend ist hier die Quelltabelle meist deutlich größer als die Zieltabelle.
INSERT Aktionen sind hier eher selten, in manchen Fällen kann MERGE durch ein entsprechendes UPDATE TABLE Statement mit EXISTS oder IN(SELECT) Konstrukten ersetzt werden. MERGE bietet im vergleich dazu aber die Möglichkeit, die Zieltabelle mit den Daten aus der Quelltabelle zu aktualisieren:
-
MERGE INTO new_customers n USING customer c ON( c.customer_no=n.customer_no ) WHEN MATCHED THEN UPDATE SET error_flag=TRUE, error_text= 'Customer-id already exists with name ' || c.first_name || ',' ||c.last_name WHERE c.first_name||c.last_name != n.first_name||n.last_name
Merge als Delta-Finder
Ein eher ungewöhnlicher Einsatzzweck für den MERGE-Befehl ist das Ermitteln von Differenzen bzw. Deltas fast identischer Tabellen. Als Beispiel dient hier ein täglicher Tabellenabzug, aus dem festgestellt werden soll, welche Zeilen seit dem Vortag neu hinzugekommen, gelöscht oder geändert worden sind.
Im Normalfall würden Sie mehrere Einzelschritte mit MINUS-Operatoren bzw. OUTER JOINs durchführen.
- Mit LEFT OUTER JOIN neue (primary key) Zeilen finden,
- Mit RIGHT OUTER JOIN gelöschte (primary key) Zeilen finden und
- Mit INNER JOIN mit Filtern geänderte (non primary key) Zeilen finden.
Alle drei Schritte können in einem einzelnen MERGE-Statement erledigt werden. Das Beispiel arbeitet destruktiv auf dem 'aktuellen' Auszug, der dazu um eine Spalte 'status_flag' erweitert wurde:
-
MERGE INTO new_customer n USING customer c ON (c.customer_no=n.customer_no) WHEN MATCHED THEN UPDATE SET status_flag='U' DELETE WHERE (c.first_name=n.first_name AND … AND c.city_id=n.city_id) WHEN NOT MATCHED THEN INSERT VALUES (customer_no, first_name, ..., city_id, 'D') ;
Ergebnis:
- Zeilen, die seit dem Vortag gelöscht wurden, waren in der today-Tabelle nicht mehr enthalten und wurden über die INSERT-Regel neu eingefügt und tragen das status_flag 'D' für delete.
- Zeilen, die noch vorhanden sind, erhalten über die UPDATE-Regel generell das Flag 'U' für update.
- Zeilen, die sich zum Vortag nicht geändert haben, werden über die zusätzliche DELETE-Regel direkt aus der today-Tabelle gelöscht.
- Zeilen, die neu hinzugekommen sind, also in yesterday noch nicht existieren, sind vom Merge unangetastet und tragen ausschließlich das default- status_flag (ggf. NULL)















