J'ai 2 déclencheurs sur une table; on travaille pour les insertions:
CREATE TRIGGER "get_user_name"
AFTER INSERT ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "add_info"();
Cela met à jour certaines valeurs dans le tableau.
[.____] et une pour les mises à jour (pour remplir une table d'histoire):
CREATE TRIGGER "set_history"
BEFORE UPDATE ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "gener_history"();
Le problème est que lorsque j'insère une nouvelle ligne dans le tableau, la procédure "add_info"()
fait une mise à jour et déclenche donc le deuxième déclencheur, qui se termine par une erreur:
ERROR: record "new" has no field "field1"
Comment puis-je éviter ça?
(Erreur évidente dans la logique de déclenchement de côté.)
[.____] dans Postgres 9.2 ou ultérieure, utilisez la fonction pg_trigger_depth()
That @ Akash déjà mentionné Dans A Condition sur la gâchette elle-même (au lieu du corps de la fonction de déclenchement), de sorte que la fonction de déclenchement n'est même pas exécutée lorsqu'elle est appelée à partir d'un autre déclencheur (y compris elle-même - évitant ainsi boucles).
[.____] Cela fonctionne généralement mieux et est plus simple et plus propre:
CREATE TRIGGER set_history
BEFORE UPDATE ON field_data
FOR EACH ROW
WHEN (pg_trigger_depth() < 1)
EXECUTE PROCEDURE gener_history();
L'expression pg_trigger_depth() < 1
est évaluée avant La fonction de déclenchement est entrée. Donc, il évalue à 0 dans le premier appel. Lorsque cela est appelé à partir d'un autre déclencheur, la valeur est plus élevée et la fonction de déclenchement n'est pas exécutée.
Si vous ne voulez pas que la mise à jour de la gâchette soit exécutée lorsque c'est appelé de l'intérieur de la gâchette insertion, vous pouvez surmonter vos instructions avec une condition de pg_trigger_depth()
qui retourne la profondeur . Ce qui ne sera pas 0 lorsque vous exécutez la gâchette directement/indirectement d'un autre déclencheur .
Donc, dans votre fonction gener_history()
, vous pouvez faire quelque chose comme ça
IF pg_trigger_depth() = 1 THEN
.. your statements..
END IF;
Voici un autre exemple: http://www.depesz.com/2012/02/01/waitting-for-9-2-trigger-depth/
Retirer le AFTER INSERT
déclencheur et appel add_info
de votre application
Changer la AFTER INSERT
déclencher dans BEFORE INSERT