Das ELSE
Niederlassung radikal vereinfacht werden. Aber ein paar weitere Dinge sind ineffizient / ungenau / gefährlich:
CREATE OR REPLACE FUNCTION sample_trigger_func()
RETURNS TRIGGER AS
$func$
BEGIN
IF TG_OP = 'DELETE' THEN
RAISE INFO 'OLD: %', OLD.name;
EXECUTE format('INSERT INTO %I SELECT ($1).*', TG_TABLE_NAME || '_deletes')
USING OLD #= hstore('{mod_op, mod_datetime}'::text[]
, ARRAY[left(TG_OP, 1), now()::text]);
RETURN OLD;
ELSE -- insert, update
NEW.mod_op := left(TG_OP, 1);
NEW.mod_datetime := now();
RETURN NEW;
END IF;
END
$func$ LANGUAGE plpgsql;
-
Im
ELSE
Verzweigung einfachNEW
zuweisen direkt. Keine Notwendigkeit für mehr dynamisches SQL, das denselben Trigger erneut auslösen und eine Endlosschleife verursachen würde. Das ist der Hauptfehler. -
RETURN NEW;
außerhalb desIF
Konstrukt würde Ihre Triggerfunktion fürDELETE
unterbrechen , seitNEW
ist für DELETES nicht zugewiesen. -
Ein Schlüsselmerkmal ist die Verwendung von
hstore
und der hstore-Operator#=
um zwei ausgewählte Felder des bekannten Zeilentyps dynamisch zu ändern - das ist unbekannt zum Zeitpunkt des Schreibens des Codes. Auf diese Weise manipulieren Sie den ursprünglichenOLD
nicht Wert, der einen überraschenden Nebeneffekt haben könnte, wenn Sie mehr Auslöser in der Ereigniskette haben.OLD #= hstore('{mod_op, mod_datetime}'::text[] , ARRAY[left(TG_OP, 1), now()::text]);
Das Zusatzmodul
hstore
muss installiert werden. Einzelheiten:- So setzen Sie den Wert eines zusammengesetzten Variablenfelds mit dynamischem SQL
- Spaltennamen dynamisch für eine Datensatzvariable in PostgreSQL übergeben
Verwenden des
hstore(text[], text[])
Variante hier, um einenhstore
zu erstellen Wert mit mehreren Feldern im laufenden Betrieb. -
Der Zuweisungsoperator in plpgsql ist
:=
: -
Beachten Sie, dass ich den Spaltennamen
mod_datetime
verwendet habe anstelle des irreführendenmod_date
, da die Spalte offensichtlich eintimestamp
ist und keindate
.
Ich habe ein paar andere Verbesserungen hinzugefügt, während ich gerade dabei bin. Und der Trigger selbst sollte so aussehen:
CREATE TRIGGER insupdel_bef
BEFORE INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE sample_trigger_func();