Gibt es eine gute Möglichkeit, einen Trigger für jeden Datensatz in einer Postgres-Tabelle auszuführen?

22

Ich habe ein System, in dem ich das Design einiger Tabellen (repliziert über Slony-I) nicht steuern kann, und daher habe ich eine Reihe von sogenannten Schattentabellen, in denen ich einige Informationen aus den replizierten Tabellen extrahiere , und speichern Sie es in der verarbeiteten Form, die ich benötige, während Sie die Datensätze entfernen, die ich ignorieren möchte.

Im Moment, nachdem ich ein neues Replikat eingerichtet habe, führe ich ein Update durch und setze einen Wert auf sich selbst zurück (z. B. UPDATE tablename SET field=field), um die Ausführung des Triggers zu erzwingen, aber einige der Tabellen sind Millionen von Datensätzen und wachsen und es kann 30 Minuten dauern . (Und dann ist da noch das Vakuum).

Gibt es eine bessere Möglichkeit, es auszulösen, oder eine Möglichkeit, eine Funktion so zu schreiben, dass sie mit übergebenen Eingaben oder NEWje nach aufrufendem Kontext funktioniert ? Ich zögere es, zwei verschiedene Funktionen beizubehalten, da ich zu oft gesehen habe, wo eine aktualisiert wird und nicht die andere.

Joe
quelle
Ich wusste, wie man einen Abzug betätigt ... Ich fragte, ob es einen guten Weg gäbe .
Joe

Antworten:

19

Dies kann mithilfe der folgenden Vorlage erfolgen:

CREATE TABLE tablename ( ... );

/* for direct invocation */
CREATE FUNCTION propagate_data(newrow tablename) RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO other_table VALUES (newrow.a, newrow.b, ...);
END:
$$;

/* trigger function wrapper */
CREATE FUNCTION propagate_data_trg() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
    PERFORM propagate_data(NEW);
END;
$$;

CREATE TRIGGER propagate_data AFTER INSERT ON tablename FOR EACH ROW
    EXECUTE PROCEDURE propagate_data_trg();
Peter Eisentraut
quelle
Doh ... Ich habe rückwärts darüber nachgedacht (versucht, die Triggerfunktion durch eine Prozedur aufrufbar zu machen, nicht umgekehrt).
Joe
1
Als ich es tatsächlich tat, stellte ich fest, dass 'row' ein reserviertes Wort war, und korrigierte das Beispiel, damit andere nicht so viel Zeit für das Debuggen aufwenden.
Joe
1
Ich hätte es wirklich vor Jahren nachholen sollen. Es hat eine Weile gedauert, bis ich alles in meinem System zum Laufen gebracht habe ... und diese Methode funktioniert, aber die Leistung war furchtbar. (es dauerte von 30 min bis über einen Tag).
Joe