Mit dem PostgreSQL Release Version 15 wurde die längst überfällige Merge-Funktion eingeführt, wodurch ein potenzieller Umstieg von Oracle auf PostgreSQL noch einfacher gestaltet werden kann – hierzu ein Anwendungsbeispiel für die Merge-Funktion.
Die Anwendungslogik
Mit unserer Beispielanwendung wollen wir simple Informationen zu einem Datenbanksystem in einer Tabelle speichern, Änderungen protokollieren und hierzu ein „Staging“-Verfahren anwenden. Wir erstellen dazu die folgenden drei Tabellen:
Neben einer Datenbank-ID wollen wir auch die Version und IP-Adresse der Datenbank speichern. Für unser Beispiel gehen wir davon aus, dass die Informationen täglich durch einen Job gesammelt und anschließend als einzelne Datensätze in die Tabelle DB_INFO_STAGE geschrieben werden.
Die Magie des Merges
Für einen Abgleich, ob es sich bei den Datensätzen aus der „Staging“-Tabelle um neue oder bereits bekannte Datensätze handelt, nutzen wir Merge innerhalb einer Prozedur:
Zunächst definieren wir innerhalb des Merges eine „Zielmenge“, welche mit der Zieltabelle DB_INFO abgeglichen werden soll:
Die Datenmenge „s“ enthält alle Datensätze der „Staging“-Tabelle abzüglich der bereits vorhandenen Datensätze aus der Zieltabelle DB_INFO. Anhand der DB_ID prüfen wir nun Datensatz für Datensatz, ob es sich um einen neuen oder veränderten Datensatz handelt:
Trifft die "ON"-Klausel zu, existiert bereits ein Datensatz für die jeweilige Datenbank. Somit muss es sich in diesem Fall um eine veränderte Information handeln. In unserem Beispiel kann sich z. B. die IP-Adresse der Datenbank verändert haben.
Das nachfolgende UPDATE-Statement passt den Datensatz in der Zieltabelle entsprechend an:
Stimmt die „ON“-Klausel nicht überein, handelt es sich um einen neuen Datensatz. Dementsprechend wird bei „not matched“ ein INSERT in die Zieltabelle ausgeführt:
Bevor die "Staging"-Tabelle abschließend wieder geleert wird, führen wir ein UPDATE auf alle übereinstimmenden DB_IDs durch und aktualisieren die „LAST_FOUND“-Spalte:
Der History-Trigger
Damit wir auch die historischen Informationen speichern können, ob sich ein Datensatz in der Zieltabelle mit der Zeit verändert hat, dieser hinzugefügt oder letztlich gelöscht wurde, benötigen wir noch einen Trigger für die Zieltabelle:
Der Trigger sorgt final dafür, dass wir in der DB_INFO_HIST-Tabelle ein Aktionsfeld mit einem I (= INSERT), D (= DELETE) oder U (= UPDATE) gefüllt bekommen. Zusammen mit dem Timestamp der Aktion lässt sich so der genaue „Zustand“ der Zieltabelle zu einem jedem beliebigen Zeitpunkt abbilden.
Der Merge in Aktion
Für unser Beispiel fügen wir zunächst vier simple Datensätze mit den DB_IDs 100, 200, 300 und 400 in die „Staging“-Tabelle ein und führen die Merge-Prozedur aus:
Bei einem Blick auf die Ziel- und History-Tabelle sehen wir nun Folgendes:
Jeder neue Datensatz wird mit einem „I“ in die History-Tabelle geschrieben. Alle Datensätze erhalten den aktuellen Timestamp als „LAST_FOUND“ bzw. „CHANGE_DATE“ gespeichert.
Nun simulieren wir einen späteren Lauf. Hier ändern wir bewusst die IP-Adressen von DB_ID 200 und 300:
Während die Ziel-Tabelle weiterhin aus den vier vorhandenen Datensätzen mit den aktuellen IP-Adressen und Timestamps besteht, wurde die History-Tabelle um die Update-Informationen zzgl. der neuen IP-Adresse erweitert.
Fazit
Die neue PostgreSQL Merge-Funktion steht den Oracle Funktionalitäten in keiner Weise nach. Die Syntax in diesem Beispiel ist bis auf 2-3 Kleinigkeiten identisch (siehe Oracle-Code unten 🠗). In Kombination mit einer zusätzlichen Trigger-Logik lässt sich so eine komplexe Staging- und History-Logik implementieren.
In meinem konkreten Beispiel habe ich die Logik aus einer Oracle-Anwendung mit wenig Aufwand auf PostgreSQL adaptiert.
Haben auch Sie einen Anwendungsfall für die Merge-Funktion oder benötigen Sie grundsätzlich Hilfe in Sachen PostgreSQL- und Oracle-Entwicklungsthemen? Sprechen Sie uns einfach an.
Seminarempfehlung
POSTGRESQL ADMINISTRATION DB-PG-01
Zum Seminar