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
ELSEbranche attribuez simplement àNEWdirectement. 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 duIFla construction casserait votre fonction de déclenchement pourDELETE, depuisNEWn'est pas attribué pour les DELETE. -
Une fonctionnalité clé est l'utilisation de
hstoreet 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 leOLDd'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
hstoredoit ê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 unhstorevaleur avec plusieurs champs à la volée. -
L'opérateur d'affectation dans plpgsql est
:=: -
Notez que j'ai utilisé le nom de colonne
mod_datetimeau lieu du trompeurmod_date, puisque la colonne est évidemment untimestampet 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();