IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PostgreSQL Discussion :

Trigger et récursivité


Sujet :

PostgreSQL

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 122
    Points
    122
    Par défaut Trigger et récursivité
    Bonjour,

    J'ai un problème de récursivité et je n'arrive pas à m'en sortir, donc je fais appel à vous.
    Soit une table "lots" qui contient le champs "nouv_lot" et une table "remplacements_lots" qui contient le champs "nouv_lot_remplace".
    Il se peut (et il y a) des "nouv_lot" qui ne sont pas dans "nouv_lot_remplace", et inversement.
    Toutefois, si un "nouv_lot" est aussi dans "nouv_lot_remplace", son champs "actif" doit être à FALSE.
    Je voulais donc faire un TRIGGER sur l'insert et sur l'update des 2 tables pour, si la valeur insérée ou modifiée dans une table est aussi dans l'autre table, mettre "actif" de "lots" à FALSE.
    J'ai donc écrit le trigger suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    CREATE OR REPLACE FUNCTION remplacement_lot()  RETURNS trigger AS
    $BODY$BEGIN
    	IF TG_TABLE_NAME = 'lots' THEN
    		IF EXISTS(SELECT nouv_lot_remplace from remplacements_lots where nouv_lot_remplace = NEW.nouv_lot) THEN
    			NEW.actif = FALSE;
    		END IF;
    	ELSE
    		IF EXISTS(SELECT nouv_lot from lots where nouv_lot = NEW.nouv_lot_remplace) THEN
    			UPDATE lots 
    			SET actif = FALSE 
    			WHERE nouv_lot = NEW.nouv_lot_remplace;
    		END IF;
    	END IF;
    	RETURN NULL;
    END;$BODY$
      LANGUAGE plpgsql VOLATILE
      COST 100;
    ALTER FUNCTION remplacement_lot()
      OWNER TO jmdeneyer;
    COMMENT ON FUNCTION remplacement_lot() IS 'Désactive le lot si le lot modifié ou inséré dans la colonne "nouv_lot_remplace" est dans la table lots';
    Mais lorsque j'ajoute ou je modifie une valeur, l'autre table se met à jour, donc déclenche le trigger, qui remodifie la première table, etc ...

    J'ai pensé diviser mon trigger en 2 pour faire un trigger pour chaque table, mais le problème sera le même, j'aurai aussi une boucle infinie.

    Comment dois-je faire pour m'en sortir ?
    Merci de vos z'avis z'avisés.
    Il n'y a pas de problèmes. Il n'y a que des solutions.
    Malheureusement, elles sont parfois un peu dur à trouver ...


    Aucune touche n'a été maltraitée pour réaliser ce texte.

  2. #2
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 122
    Points
    122
    Par défaut
    Je m'auto-répond, mais je publie la réponse pour le cas où quelqu'un en aurait besoin.

    Voici le trigger final et fonctionnel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    CREATE OR REPLACE FUNCTION remplacement_lot()  RETURNS trigger AS
    $BODY$BEGIN
    	IF TG_TABLE_NAME = 'lots' THEN
    		IF EXISTS(SELECT nouv_lot_remplace from remplacements_lots where nouv_lot_remplace = NEW.nouv_lot) THEN
    			NEW.actif = FALSE;
    		END IF;
    		RETURN NEW;
    	ELSE
    		IF EXISTS(SELECT nouv_lot from lots where nouv_lot = NEW.nouv_lot_remplace AND actif = TRUE) THEN
    			UPDATE lots 
    			SET actif = FALSE 
    			WHERE nouv_lot = NEW.nouv_lot_remplace;
    		END IF;
    	END IF;
    	RETURN NULL;
    END;$BODY$
      LANGUAGE plpgsql VOLATILE
      COST 100;
    ALTER FUNCTION remplacement_lot()
      OWNER TO jmdeneyer;
    COMMENT ON FUNCTION remplacement_lot() IS 'Désactive le lot si le lot modifié ou inséré dans la colonne "nouv_lot_remplace" est dans la table lots;
    J'ai ajouté un test lorsque la table source n'est pas la table "lots". Dans ce cas, en plus de tester si le nouv_lot est dans la table, on teste aussi si le champs "actif" est à TRUE, ce qui a pour effet que lorsqu'on modifie la table remplacements_lots, le trigger passe et modifie la table lots. Il repasse une seconde fois, puisque la table "lots" a été modifiée, mais après il s'arrête puisque le champs "actif" est à FALSE.

    Il y a peut-être moyen de ne pas passer le trigger plusieurs fois, mais au moins ça a le mérite de fonctionner.
    Il n'y a pas de problèmes. Il n'y a que des solutions.
    Malheureusement, elles sont parfois un peu dur à trouver ...


    Aucune touche n'a été maltraitée pour réaliser ce texte.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Cours : algorithmes et récursivité
    Par Community Management dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 17/10/2018, 00h38
  2. [power designer et Sybase] trigger
    Par mr_qno dans le forum Sybase
    Réponses: 4
    Dernier message: 12/07/2006, 18h32
  3. Réponses: 13
    Dernier message: 22/06/2006, 09h00
  4. [PostgreSQL] Refus de STATEMENT dans un trigger
    Par alex2205 dans le forum Requêtes
    Réponses: 3
    Dernier message: 10/03/2003, 12h51
  5. [Comparatif] Procédures stockées, triggers, etc.
    Par MCZz dans le forum Décisions SGBD
    Réponses: 3
    Dernier message: 28/08/2002, 12h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo