De ELSE
tak kan radicaal worden vereenvoudigd. Maar nog een paar dingen zijn inefficiënt / onnauwkeurig / gevaarlijk:
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;
-
In de
ELSE
tak toewijzen aanNEW
direct. Geen behoefte aan meer dynamische SQL - die dezelfde trigger opnieuw zou activeren en een eindeloze lus zou veroorzaken. Dat is de primaire fout. -
RETURN NEW;
buiten deIF
construct zou je triggerfunctie breken voorDELETE
, sindsNIEUW
is niet toegewezen voor VERWIJDEREN. -
Een belangrijk kenmerk is het gebruik van
hstore
en de hstore-operator#=
om twee geselecteerde velden van het bekende rijtype dynamisch te wijzigen - dat is onbekend op het moment van schrijven van de code. Zo knoei je niet met de origineleOUD
waarde, wat een verrassend neveneffect kan hebben als je meer triggers hebt in de keten van gebeurtenissen.OLD #= hstore('{mod_op, mod_datetime}'::text[] , ARRAY[left(TG_OP, 1), now()::text]);
De aanvullende module
hstore
moet geïnstalleerd worden. Details:- Hoe de waarde van het samengestelde variabele veld in te stellen met behulp van dynamische SQL
- Dynamisch doorgeven van kolomnamen voor een recordvariabele in PostgreSQL
De
hstore(text[], text[])
variant hier om een hstore
te construeren waarde met meerdere velden on-the-fly. -
De toewijzingsoperator in plpgsql is
:=
: -
Merk op dat ik de kolomnaam
mod_datetime
heb gebruikt in plaats van de misleidendemod_date
, aangezien de kolom duidelijk eentijdstempel
is en niet eendatum
.
Ik heb een paar andere verbeteringen toegevoegd terwijl ik bezig was. En de trigger zelf zou er zo uit moeten zien:
CREATE TRIGGER insupdel_bef
BEFORE INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE sample_trigger_func();