Le ELSE
branche peut être radicalement simplifiée. Mais quelques autres éléments sont inefficaces/inexacts/dangereux :
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;
-
Dans le
ELSE
branche attribuez simplement àNEW
directement. Pas besoin de SQL plus dynamique - qui déclencherait à nouveau le même déclencheur, provoquant une boucle sans fin. C'est l'erreur principale. -
RETURN NEW;
en dehors duIF
la construction casserait votre fonction de déclenchement pourDELETE
, depuisNEW
n'est pas attribué pour les DELETE. -
Une fonctionnalité clé est l'utilisation de
hstore
et l'opérateur hstore#=
pour modifier dynamiquement deux champs sélectionnés du type de ligne bien connu - qui est inconnu au moment de l'écriture du code. De cette façon, vous ne modifiez pas leOLD
d'origine valeur, ce qui peut avoir des effets secondaires surprenants si vous avez plus de déclencheurs dans la chaîne d'événements.OLD #= hstore('{mod_op, mod_datetime}'::text[] , ARRAY[left(TG_OP, 1), now()::text]);
Le module supplémentaire
hstore
doit être installé. Détails :- Comment définir la valeur d'un champ de variable composite à l'aide de SQL dynamique
- Passer dynamiquement des noms de colonne pour une variable d'enregistrement dans PostgreSQL
Utilisation de
hstore(text[], text[])
variant ici pour construire unhstore
valeur avec plusieurs champs à la volée. -
L'opérateur d'affectation dans plpgsql est
:=
: -
Notez que j'ai utilisé le nom de colonne
mod_datetime
au lieu du trompeurmod_date
, puisque la colonne est évidemment untimestamp
et non unedate
.
J'ai ajouté quelques autres améliorations tout en y étant. Et le déclencheur lui-même devrait ressembler à ceci :
CREATE TRIGGER insupdel_bef
BEFORE INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE sample_trigger_func();