Dynamischer Zugriff auf new- bzw. old-Werte in Triggern

Hallo zusammen,

ich möchte eine einzige Trigger-Funktion für eine größere Anzahl Tabellen schreiben, die folgendes durchführt:

  1. Bestimmen der primary keys der jeweils aufrufenden Tabelle (diese haben im Normalfall alle unterschiedliche Bezeichnungen)
  2. Protokollierung in der Form “adressen.id = 34”

Zu 1) habe ich folgenden Weg gefunden

  • Trigger-Input TG_RELNAME (im Beispiel “adressen”)
  • Über SELECT’s auf pg_class, pg_constraint und pg_attribute --> Spalten-Name (im Beispiel “id”)

Was mir jetzt fehlt, ist der tatsächliche Feld-Inhalt (34) aus dem NEW- bzw. OLD-Datensatz.

Ich wüsste durch die obigen SELECTS, wie die Spalte in den NEW/OLD-Sätzen heisst und auch, an der wie vielten Spalte diese steht. Kann ich mit diesem Wissen irgendwie dynamisch auf den Inhalt zugreifen?

Es wäre super, wenn mir hier jemand helfen könnte. Das würde mir eine Menge neuer Trigger-Funktionen sparen. Denn die Alternative wäre, für jede Tabelle eine eigene Funktion zu bauen, denn pro Tabelle weiss ich ja die PK-Namen. Aber das möchte ich wegen der relativ großen Anzahl Tabellen vermeiden.

Gruß
Frank

hi,

grüße nach weiden. ist ja nicht so weit weg von mir und ich bin öfters dort :wink:

aber nun zu deiner frage. mir ist nicht ganz schlüssig was du willst. ein trigger wird doch ausgeführt wenn du einen datensatz anlegst, änderst oder löscht. dieser eine datensatz ist im prinzip durch NEW (die neuen daten) bzw OLD (bei update und delete = die alten daten) bekannt. dadurch weißt du doch sehr genau welchen ds zu updatest/löscht oder einfügst.

irgendwie versteh ich nicht, was du willst. sry.

cu tb.

Servus und Grüße zurück, ’ :smiley:
Very Happy

prinzipiell klingt das ganz einfach, ich weiss…
Ist es auch, wenn ich pro Tabelle genau 1 Trigger-Funktion mache (also bei 50 Tabellen 50 Trigger-Funktionen).

Mein Ziel ist es aber, für ALLE Tabellen zusammen genau 1 Funktion zu machen.

Somit muss diese allgemeine Funktion beispielsweise mit einer Tabelle adressen und dessen Spalten-Namen z. B. AdressId genauso klar kommen wie mit einer Tabelle buchungen mit einer Spalte BuchungsId.

Mit Aufruf des Triggers bekommt man die alten bzw. neuen Daten in den Trigger rein, aber mir fehlt eine Zugriffsmöglichkeit.

Für die genannte Tabelle Adressen heisst der Zugriff auf die ID new.AdressId;
dies geht aber nicht für die Tabelle Buchungen, da der Aufruf hier new.BuchungsId heissen würde.
Würde ich jetzt für die Tabelle Adressen einen eigenen Trigger machen und für die Buchungen ebenfalls einen eigenen, wär’s easy.
Ich würde im ersten Fall die new.adressid wegprotokollieren und in der zweiten Funktion die new.buchungsid.

Aber ich will eben eine (1) Funktion für ALLE Tabellen.

Ich bräuchte somit einen Aufruf in der Form “new.$1” oder so ähnlich, so dass ich durch entsprechendes Füllen der Variablen eben beispielsweise genau auf das erste Element im RECORD komme.
Dies wäre ja bei Übergabe der Tabelle adressen genau die AdressId und bei Übergabe der Buchungen die BuchungsId.

Es geht mir gar nicht mal um das Einfügen von 50 Triggerfunktionen, auch wenn’s nicht optimal ist. Noch weniger schön ist es, wenn neue Tabellen dazu kommen oder sich die Tabellenspalten ändern. Dann darf nicht vergessen werden, auch den Trigger entsprechend anzupassen. Und genau das will ich, wenn’s kein zu großer Aufwand ist, umgehen.


Frank

Ich glaube, ich verstehe dein Problem. Da wirst du aber um einige Scriptspielereien wohl nicht herumkommen. Als ersten Ansatz würde ich dir das information_schema empfehlen, dort dürftest du alle Informationen finden, die du über die jeweilige Tabelle suchst.

An deiner Stelle wäre ich allerdings vorsichtig, das diese Funktion deine Inserts nicht allzusehr verlangsamt.

Du könntest das ganze alternativ auch in C schreiben, dann kannst du etwas Performance sparen und wenn ich mich richtig erinnere, auch direkt über C-Funktionen die Spaltennamen herausfinden.
Ist aber ne Weile her, das ich mein Modul geschrieben habe.

Ich glaube, es ist wirklich besser, das ganze irgendwie anders zu lösen. Vermutlich werde ich für jede Tabelle eine eigene Funktion schreiben.

Danke für die Info.

Hallo,

bin erst vor kurzem auf dieses Forum gestoßen, weil ich eine Lösung für dasselbe Problem suche.

Mein Ansatz wäre der folgende in Perl:

create or replace function test_trig&#40]

Leider bekomme ich beim Erzeugen der Funktion eine Perl-Fehlermeldung:

[code]
# \i test_trig.sql
psql:test_trig.sql:8: FEHLER:  creation of Perl function failed: Type of arg 1 to keys must be hash (not hash element) at line 3, near "})
        "

Wahrscheinlich nur 'ne Kleinigkeit, aber ich komme nicht darauf, wie ich über $_TD->{new} iterieren kann.

Bye…

Dirk

Mit der folgenden Schleife klappt’s dann auch:

[code]
while (($column, $value) = each %{$_TD->{new}})
{
next unless (defined ($value));
elog (INFO, “$column=$value”);
}


Bye...

Dirk