Il ELSE ramo può essere radicalmente semplificato. Ma un altro paio di cose sono inefficienti/imprecise/pericolose:
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
ELSEbranch basta assegnare aNEWdirettamente. Non c'è bisogno di un SQL più dinamico, che attiverebbe di nuovo lo stesso trigger causando un ciclo infinito. Questo è l'errore principale. -
RETURN NEW;al di fuori delIFcostrutto interromperebbe la tua funzione di attivazione perDELETE, poichéNEWnon è assegnato ai DELETE. -
Una caratteristica fondamentale è l'uso di
hstoree l'operatore hstore#=per modificare dinamicamente due campi selezionati del tipo di riga noto - cioè sconosciuto al momento della scrittura del codice. In questo modo non manometterai ilOLDoriginale valore, che potrebbe avere effetti collaterali sorprendenti se hai più trigger lungo la catena di eventi.OLD #= hstore('{mod_op, mod_datetime}'::text[] , ARRAY[left(TG_OP, 1), now()::text]);Il modulo aggiuntivo
hstoredeve essere installato. Dettagli:- Come impostare il valore del campo della variabile composita utilizzando SQL dinamico
- Trasferimento dinamico dei nomi di colonna per una variabile record in PostgreSQL
Utilizzando
hstore(text[], text[])variante qui per costruire unhstorevalore con più campi al volo. -
L'operatore di assegnazione in plpgsql è
:=: -
Nota che ho usato il nome della colonna
mod_datetimeinvece dell'ingannevolemod_date, poiché la colonna è ovviamente untimestampe non unadate.
Ho aggiunto un paio di altri miglioramenti mentre ci lavoravo. E il trigger stesso dovrebbe assomigliare a questo:
CREATE TRIGGER insupdel_bef
BEFORE INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE sample_trigger_func();