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
ELSEVerzweigung einfachNEWzuweisen 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 desIFKonstrukt würde Ihre Triggerfunktion fürDELETEunterbrechen , seitNEWist für DELETES nicht zugewiesen. -
Ein Schlüsselmerkmal ist die Verwendung von
hstoreund 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ünglichenOLDnicht 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
hstoremuss 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 einenhstorezu erstellen Wert mit mehreren Feldern im laufenden Betrieb. -
Der Zuweisungsoperator in plpgsql ist
:=: -
Beachten Sie, dass ich den Spaltennamen
mod_datetimeverwendet habe anstelle des irreführendenmod_date, da die Spalte offensichtlich eintimestampist 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();