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

Oracle Discussion :

[ORA-36]Oracle9i: Comment éviter la récursivité suite à l'exécution d'un trigger


Sujet :

Oracle

  1. #1
    Ito
    Ito est déconnecté
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 56
    Points : 35
    Points
    35
    Par défaut [ORA-36]Oracle9i: Comment éviter la récursivité suite à l'exécution d'un trigger
    Bonjour,

    Voici mon problème:

    La situation:
    - j'ai une procédure stockée Y qui fait INSERT ou UPDATE dans une table X
    - je veux modifier un champ de X (libellé) si son identifiant est modifié lors de la procédure Y
    - pour éviter l'erreur de table mutante, j'ai créé 2 triggers:
    1) un trigger de niveau LIGNE qui mémorise chacune des lignes modifiées de X avec un BEFORE or UPDATE on X FOR EACH ROW
    Il exécute la mémorisation avant la modification de chaque ligne

    2) un trigger de niveau INSTRUCTION avec un AFTER or UPDATE on X
    Il autorise l'accés à la table mutante X au travers de la procédure Z créée pour faire l'UPDATE sur le libellé de X

    Résultat:
    Au chargement de X j'ai l'erreur: ORA-00036: maximum number of recursive SQL levels (string) exceeded
    Il y a un problème de récursivité. Comment le résoudre ?

    Merci d'avance pour toute suggestion.

  2. #2
    Expert éminent sénior
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Points : 11 862
    Points
    11 862
    Par défaut
    Une solution serait peut-être de désactiver/réactiver le trigger dans la procédure autonome...

    A tester.

  3. #3
    Ito
    Ito est déconnecté
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 56
    Points : 35
    Points
    35
    Par défaut
    Citation Envoyé par SheikYerbouti
    Une solution serait peut-être de désactiver/réactiver le trigger dans la procédure autonome...

    A tester.
    Ok, mais quelle procédure autonome: la Y (UPDATE sur la table X) ou la Z (proc d'UPDATE appelée dans le trigger) ?

  4. #4
    Expert éminent sénior
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Points : 11 862
    Points
    11 862
    Par défaut
    Celle qui met à jour la table sur laquelle se déclenche le trigger.

  5. #5
    Ito
    Ito est déconnecté
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 56
    Points : 35
    Points
    35
    Par défaut
    Citation Envoyé par SheikYerbouti
    Celle qui met à jour la table sur laquelle se déclenche le trigger.
    Bonjour,

    J'ai compris ce qu'il faut faire et j'ai essayé ceci:

    create or replace procedure Y is

    begin
    -- désactivation du trigger
    alter table X disable trigger trig1;

    begin
    insert into X.....;
    commit;
    exception...
    end;

    begin
    update X set......;
    commit;
    exception...;
    end;

    -- réactivation du trigger
    alter table X enable trigger trig1;

    end Y;
    /

    Le compilateur n'aime et j'ai le message d'erreur

    PLS-00103: Encountered the symbol "ALTER" when expecting one of
    the following:
    begin case declare exit for goto if loop mod null pragma
    raise return select update while with <an identifier>
    <a double-quoted delimited-identifier> <a bind variable> <<
    close current delete fetch lock insert open rollback
    savepoint set sql execute commit forall merge
    <a single-quoted SQL string> pipe

    Ma question: où et comment dois-je placer la désactivation du trigger ?

  6. #6
    Membre expert

    Profil pro
    Inscrit en
    Février 2006
    Messages
    3 437
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 3 437
    Points : 3 597
    Points
    3 597
    Par défaut
    Il faut utiliser EXECUTE IMMEDIATE et être sûr d'avoir le privilège correspondant directement donné par un GRANT et non par un rôle.

  7. #7
    Expert éminent sénior
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Points : 11 862
    Points
    11 862
    Par défaut
    1. une procédure autonome doit incluse lr mot clé:
    PRAGMA AUTONOMOUS_TRANSACTION

    2. Vous ne pouvez pas utiliser directement un ordre du DDL, vous devez l'encapsuler dans une instruction EXECUTE IMMEDIATE

  8. #8
    Membre averti Avatar de Wurlitzer
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 469
    Points : 408
    Points
    408
    Par défaut
    Desactiver le trigger ? Et que se passe t il si quelqu'un d'autre met a jour X pendant ce temps. Le trigger ne se declenchera pas non plus et l'on mémorisera pas la modification de X.

    Je n'ai malheureusement pas la solution mais la desactivation du trigger ne me semble pas une bonne voie.

  9. #9
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Ito
    La situation:
    - j'ai une procédure stockée Y qui fait INSERT ou UPDATE dans une table X
    - je veux modifier un champ de X (libellé) si son identifiant est modifié lors de la procédure Y
    - pour éviter l'erreur de table mutante, j'ai créé 2 triggers:
    Salut,
    Je n'arrive pas à comprendre le fonctionnement

    1/ Tu fais des INSERT ou UPDATE par une procédure Y
    2/ Tu ne veux modifier le champ X(lib) que si le champ X'(id) a été modifié par la procédure Y et pas par une autre

    Si c'est ça, rajoute une colonne PROC NUMBER(1)
    Dans ta proc Y tu mets à jour cette colonne PROC = 1
    Tu crées un trigger sur X(id) et tu testes si proc=1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    AFTER UPDATE OF X(id) FOR EACH ROWS
    WHEN (:new.Proc = 1)
    BEGIN
     :new.proc := NULL;
     :new.X(lib) := 'modif';
    END;

  10. #10
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    l'idéal c'est de créer une variable de session (une variable dans un package) et de modifier sa valeur pour indiquer au trigger qu'il ne doit pas se déclencher

  11. #11
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Yop, bien plus net.

  12. #12
    Membre émérite Avatar de Drizzt [Drone38]
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2004
    Messages
    1 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 001
    Points : 2 453
    Points
    2 453
    Par défaut
    Petite question en rapport avec la solution de Fred_D.

    Comment faire pour que le trigger sache qu'il ne doit pas s'executer ?

    Est-ce que tu veux juste dire faire un (en resume) if <variable_global> à 0 then exit;

    ou peut-on ajouter dans les conditions de declanchement du trigger (avant le begin) quelque chose la dessus.

    Car dans mon cas, j'ai un trigger que j'aimerai bien desactiver pour la duree d'une procédure mais je ne peux pas car d'autres traitements peuvent avoir besoin de ce trigger.
    Ce qui pose probleme ce n'est pas tant le traitement qu'effectue le trigger mais plutot le temps d'execution. Ma procédure faisant beaucoup de mise à jour declancheuse du trigger, meme avec un trigger vide ca prends enormement de temps. Alors qu'avec un trigger inactif c'est tres rapide. L'ideal serait donc une solution ne provoquant pas du tout l'activation du trigger tout en le laissant actif pour d'autres procédures.

    Merci d'avance pour d'éventuelles idées.

  13. #13
    Nouveau membre du Club
    Inscrit en
    Juin 2004
    Messages
    53
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 53
    Points : 39
    Points
    39
    Par défaut
    Tu dis que ton trigger met à jour un champ Y quand le champ X est modifié.
    Doit-il aussi se déclencher quand tu mets à jour le champ Y ?
    Si non, le plus simple est de préciser dans ton trigger qu'il ne se déclenche que si le champ X est modifié ?
    Quelque chose du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    trigger toto_avant before update of champ X on la_table for each row...
     
    trigger toto_apres after update of "champ X" on la_table ...

  14. #14
    Membre émérite Avatar de Drizzt [Drone38]
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2004
    Messages
    1 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 001
    Points : 2 453
    Points
    2 453
    Par défaut
    C'est pas exactement ça, j'ai mal du m'exprimer, je vais reouvrir un poste ou je vais mieux decrir mon problème ça sera plus simple.

Discussions similaires

  1. Comment éviter la décompilation d'un exécutable ?
    Par pierre1492 dans le forum Langage
    Réponses: 10
    Dernier message: 07/05/2006, 10h42
  2. Comment éviter les doublons dans ma table
    Par einegel dans le forum Bases de données
    Réponses: 3
    Dernier message: 09/11/2004, 13h18
  3. [TEdit] Comment éviter le bip ?
    Par portu dans le forum Composants VCL
    Réponses: 4
    Dernier message: 01/10/2004, 13h01
  4. Réponses: 4
    Dernier message: 28/07/2004, 11h42
  5. [eclipse 2.1][compilation] Comment éviter...
    Par ftrifiro dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 29/06/2004, 17h16

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