# Replikationsereignis-Prozeduren (Umgang mit eigenen Triggern & Views in PostgreSQL)

<span class="custom-button red-button">Gen. 24 Enterprise</span>

## Tabelle nach Strukturänderung: Löschen und Neu-Übertragen

Bei jeder Struktur-Änderung einer Tabelle (z. B. Hinzufügen eines Selektionsfeldes oder ggf. bei Updates der Software) wird diese in der SQL-Replikation komplett gelöscht und neu übertragen. Das ist wichtig, um stets die aktuelle Struktur zu gewährleisten. Es bedeutet aber auch, dass alle selbst angelegten Views und Trigger, die sich auf eine durch die Replikation erstellte Tabelle beziehen, gelöscht werden.

## Auszuführender SQL-Befehl nach Update Replikationstabelle

Mit folgendem SQL-Befehl kann in PostgreSQL eine Prozedur angelegt werden, die nach einem Update einer Replikationstabelle ausgeführt wird. Dabei ist ```[Schemaname]``` durch den Namen des Schemas zu ersetzen, welches als Ziel für die Replikation eingerichtet wurde und ```[Tabellenname]``` mit dem Namen der Replikationstabelle, nach deren Update die Prozedur ausgeführt werden soll.

``` sql title="Anlegen einer Stored Procedure am Beispiel onAfter_ApplyUpdates"
CREATE OR REPLACE PROCEDURE [Schemaname].[Tabellenname]_onAfter_ApplyUpdates(oldLSN BIGINT, newLSN BIGINT)
LANGUAGE plpgsql
AS $$
BEGIN
  -- Hier beliebigen Inhalt der Prozedur einfügen
END;
$$;
```

Auf vergleichbare Art und Weise können weitere Prozeduren angelegt werden, die zu bestimmten Zeitpunkten der Replikation aufgerufen werden.

| Prozedurname                                                                    | Aufruf                                                                                                              | Möglicher Einsatzzweck                                                                                                                                                                                                                                                                                                                                                                                                        |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ```[Schemaname].onBeforeAll_ApplyUpdates()```                                         | Bevor die erste Replikationstabelle angelegt oder aktualisiert wird.                                                | Trigger deaktivieren.                                                                                                                                                                                                                                                                                                                                                                                                         |
| ```[Schemaname].[Tabellenname]_onAfter_ApplyNew()```                                  | Nachdem eine Replikationstabelle neu angelegt wurde.                                                                | Anlegen von Triggern oder Views, die nicht auf andere Replikationstabellen zugreifen.                                                                                                                                                                                                                                                                                                                                         |
| ```[Schemaname].[Tabellenname]_onBefore_ApplyUpdates(oldLSN BIGINT, newLSN BIGINT)``` | Bevor eine Replikationstabelle aktualisiert wird.                                                                   | Trigger deaktivieren.                                                                                                                                                                                                                                                                                                                                                                                                          |
| ```[Schemaname].[Tabellenname]_onAfter_ApplyUpdates(oldLSN BIGINT, newLSN BIGINT)```  | Nachdem eine Replikationstabelle aktualisiert wurde.                                                                | Reaktivieren von Triggern, Ausführen von Berechnungen mit Werten aus den Feldern der Replikationstabelle oder Kopieren von Daten in Anwendertabellen. Alle Aktionen sind nur dann an dieser Stelle sinnvoll, wenn sie nicht auf andere Replikationstabellen zugreifen. Ansonsten wird die Verwendung von ```onAfterAll_ApplyUpdates``` empfohlen, da die Aktualisierungsreihenfolge der Replikationstabellen nicht garantiert wird. |
| ```[Schemaname].onAfterAll_ApplyNew()```                                              | Zum Abschluss der Replikation, wenn dabei mindestens eine Replikationstabelle neu angelegt wurde.                   | (Wieder-) Anlegen von Views, die auf mehrere Replikationstabellen zugreifen (z. B. mittels ```JOIN```). Diese Stored Procedure wird immer als Beispiel angelegt. Wenn sie bereits existiert, wird sie nicht überschrieben. Der Inhalt ist ein Beispiel, welches eine View mit einem ```JOIN``` aus Adressen und Anschriften anlegt. Der Inhalt dieser Stored Procedure kann vom Anwender frei angepasst werden.                           |
| ```[Schemaname].onAfterAll_ApplyUpdates()```                                          | Zum Abschluss der Replikation, wenn dabei mindestens eine Replikationstabelle neu angelegt oder aktualisiert wurde. | Aktualisieren von Anwendertabellen, die Daten aus mehreren Replikationstabellen beziehen (z. B. mittels ```JOIN```).



``` sql title="Automatisch angelegte Prozedur onAfterAll_ApplyNew"
CREATE OR REPLACE PROCEDURE [Schemaname].onAfterAll_ApplyNew()
LANGUAGE plpgsql
AS $$
BEGIN
  /*
  -- Anwendungsbeispiel: Replikationstabellenübergreifende View
  CREATE OR REPLACE VIEW [Schemaname].Adressen_Anschriften AS
  SELECT
    Adr.AdrNr AS Nummer,
    Adr.Status AS Status,
    An.StdReKz AS Standard_Rechnungsanschrift_Kennzeichen,
    An.StdLiKz AS Standard_Lieferanschrift_Kennzeichen,
    An.Na2 AS Name_Firma,
    An.Str AS Straße,
    An.PLZ AS PLZ,
    An.Ort AS Ort,
    An.Tel AS Telefon,
    An.EMail1 AS EMail
  FROM [Schemaname].Adressen Adr LEFT JOIN [Schemaname].Anschriften An
  ON Adr.AdrNr = An.AdrNr;
  */
END;
$$;
```

Da diese Stored Procedures (z. B. im Gegensatz zu Views) für PostgresSQL in keiner Abhängigkeit mit den Replikationstabellen stehen, werden sie auch beim Neuanlegen der Replikationstabelle wegen Änderung der Tabellenstruktur (z. B. wegen Hinzufügen von Feldern) nicht automatisch entfernt.

## Empfehlung

Wenn Trigger oder Views verwendet werden, dann sollen diese innerhalb von ```[Schemaname].onAfterAll_ApplyNew()``` angelegt werden. Nur so ist sichergestellt, dass diese immer verfügbar sind und immer eine aktuelle Struktur haben.
