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

PL/SQL Oracle Discussion :

Problème avec un trigger : table mutante


Sujet :

PL/SQL Oracle

  1. #1
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    167
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 167
    Points : 85
    Points
    85
    Par défaut Problème avec un trigger : table mutante
    Bonjour,

    alors voila j'ai l'erreur ORA-04091 qui me parle de table mutante.

    J'ai lu ce tutoriel http://sgbd.developpez.com/oracle/ora-04091/ mais je ne comprends toujours pas.

    J'ai un trigger qui doit mettre à jour un montant de séjour, dès que l'on insère une participation à une activité.

    Je met à jour mon montant après l'ajout d'une participation. Les clés primaires de la table PARTICIPE sont 2 clés externes: no_sejour (table SEJOUR) et no_activite (table ACTIVITE).

    Voici le code de mon trigger :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    CREATE OR REPLACE TRIGGER majFacture AFTER INSERT ON PARTICIPE FOR EACH ROW DECLARE
    	v_nb_unites NUMBER;
    	v_prix_unite NUMBER;
    BEGIN
    	SELECT :NEW.nb_unites INTO v_nb_unites FROM PARTICIPE;
     
    	SELECT a.prix_unite INTO v_prix_unite FROM ACTIVITE a 
    	WHERE :NEW.no_activite = a.no_activite;
     
    	UPDATE SEJOUR SET montant_sejour = montant_sejour + (v_nb_unites * v_prix_unite) 
    	WHERE SEJOUR.no_sejour = :NEW.no_sejour;
    END;
    Je vous remercie de m'aider car je ne vois vraiment pas quoi faire.
    "La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. Ici, nous avons réuni théorie et pratique : Rien ne fonctionne... et personne ne sait pourquoi !" -Albert Einstein

  2. #2
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Quel est l'intérêt de cette requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT :NEW.nb_unites INTO v_nb_unites FROM PARTICIPE;
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  3. #3
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    167
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 167
    Points : 85
    Points
    85
    Par défaut
    Je sauvegarde dans une variable le nombre d'unités que je viens d'insérer.

    Pourquoi, je peux l'éviter ?
    "La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. Ici, nous avons réuni théorie et pratique : Rien ne fonctionne... et personne ne sait pourquoi !" -Albert Einstein

  4. #4
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Citation Envoyé par Raiden1234 Voir le message
    Je sauvegarde dans une variable le nombre d'unités que je viens d'insérer.

    Pourquoi, je peux l'éviter ?
    :NEW.nb_unites est une variable. Ce que tu fais reviens à faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    v_nb_unites := :NEW.nb_unites;
    Sans compter que tu risque d'avoir une exception too_many_rows qui se déclenche si tu as plusieurs ligne dans ta table participe.
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  5. #5
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    167
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 167
    Points : 85
    Points
    85
    Par défaut
    SUPER ! J'ai fait comme vous m'avez dit et maintenant ça marche merci.

    J'en profite pour vous montrer un autre script qui me générait la même erreur.

    J'ai essayé d'adapter votre solution à mon script mais j'ai l'impression que cette fois-ci ce n'est plus la même erreur, auriez-vous une fois de plus l'élément de solution ?

    Ce trigger doit tout simplement supprimer un sejour si la ou LES facture(s) associée(s) ont été réglé (acquittee = 1).

    Donc en fait je compte le nombre de facture pour un estivant, et ensuite à l'aide d'un compteur je supprime si les factures ont toutes été réglées.

    Voici le code associé :

    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
     
    CREATE OR REPLACE TRIGGER invalider BEFORE UPDATE OF acquittee ON FACTURE FOR EACH ROW DECLARE 
      compteur NUMBER := 0;
      nb NUMBER;
     
    BEGIN
        SELECT COUNT(acquittee) INTO nb FROM FACTURE WHERE FACTURE.no_estivant = :NEW.no_estivant;
        FOR record IN(SELECT acquittee FROM FACTURE WHERE FACTURE.no_estivant = :NEW.no_estivant)
          LOOP
    	IF record.acquittee = 1 THEN
    		compteur := compteur + 1;
            END IF;
    	IF record.acquittee = 1 AND compteur = nb THEN
              	DELETE FROM SEJOUR WHERE :NEW.no_facture = SEJOUR.no_sejour;
        	END IF;
          END LOOP;
    END;
    "La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. Ici, nous avons réuni théorie et pratique : Rien ne fonctionne... et personne ne sait pourquoi !" -Albert Einstein

  6. #6
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Là c'est un peu plus compliqué.

    Tu as plusieurs solutions. La plus simple à mon avis, est de supprimer les séjours dont toutes les factures ont été acquittées dans un trigger after update global (=> pas for each row).
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  7. #7
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    167
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 167
    Points : 85
    Points
    85
    Par défaut
    Je n'arrive pas à caser le global car il n'arrive pas à comprendre l'expression du trigger si je l'écrit.

    Avec un simple after update, j'ai ce fameux problème de référence interdite vers :NEW. Problème que j'avais justement contourné avec les for each row
    "La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. Ici, nous avons réuni théorie et pratique : Rien ne fonctionne... et personne ne sait pourquoi !" -Albert Einstein

  8. #8
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    T'as pas besoin de faire référence à :new ou :old.

    Tu supprimes tous les séjours dont toutes les factures sont acquitées.
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  9. #9
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    167
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 167
    Points : 85
    Points
    85
    Par défaut
    ok je vais voir ça

    Merci beaucoup pour votre aide !
    "La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. Ici, nous avons réuni théorie et pratique : Rien ne fonctionne... et personne ne sait pourquoi !" -Albert Einstein

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

Discussions similaires

  1. Problème trigger : table mutante
    Par coboy dans le forum PL/SQL
    Réponses: 0
    Dernier message: 12/12/2008, 11h08
  2. Probleme trigger-tables mutantes
    Par scariou29 dans le forum Administration
    Réponses: 2
    Dernier message: 17/11/2006, 17h13
  3. Problème avec un trigger...
    Par nasgektw dans le forum Développement
    Réponses: 3
    Dernier message: 28/04/2006, 17h41
  4. Réponses: 12
    Dernier message: 25/11/2005, 12h29
  5. [T-SQL] problème avec un trigger
    Par karine77 dans le forum Adaptive Server Enterprise
    Réponses: 3
    Dernier message: 26/09/2005, 10h45

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