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 de trigger qui déclenche un autre trigger


Sujet :

PL/SQL Oracle

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur Back-End
    Inscrit en
    Avril 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Back-End

    Informations forums :
    Inscription : Avril 2006
    Messages : 113
    Points : 49
    Points
    49
    Par défaut Problème de trigger qui déclenche un autre trigger
    Bonjour à tous

    En ce moment, je travaille sur projet en base de donnée distribuée, sql*plus.
    Je crée des trigger qui réplique des tables, bref.

    J'ai un sérieux soucis, lorsque j'ai une insertion sur une table A, le trigger A se déclanche, mais à l'intérieur, il y a une instruction qui déclanche le trigger B. Et le Trigger B lit la table qui lance trigger A. Donc il y a problème de nuting avec l'exécution du Trigger A, lors de l'insertion de la Tabla A.

    Donc la solution c'est de désactiver le Trigger B quand il trigger A s'exécute, mais comment le faire d'une manière dynamique. ça fonctionne si avant mon insertion je désactive le trigger B puis après insertion de la table A je le réactive, mais ça va pas du tout cette solution il faut que ça soit automatique.


    Donc j'ai essayé une autre solution avec execute immediate en créant une procédure qui active et désactive le trigger, mais quand je lance cette procédure dans le trigger il me dit le message suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
     
    ERROR at line 1: 
    ORA-04092: cannot COMMIT in a trigger 
    ORA-06512: at "DAV79.CONTROLARREPLICDEPARTAMENTO", line 6 
    ORA-06512: at "DAV79.ACTUALIZAREMPLEADOORAGEN", line 9 
    ORA-04088: error during execution of trigger 'DAV79.ACTUALIZAREMPLEADOORAGEN'
    Donc je sais pas si c'est un prolbème de droit, je sais qu'un trigger n'accepte pas des instruction LDD, mais je pensais qu'avec une instruction execute immediate ça paserait, car ça permet d'exécuter n'importe quel comande sql natif. Mais pour l'instant je n'ai pas trouvé la solution.

    Je peux vous faire voir mon code mais c'est un peu compliqué à expliquer

    voici mon trigger A :


    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
    22
     
    create or replace trigger actualizarEmpleadoOragen
    after insert on Empleado 
    for each row
    declare
        encontrar integer; 
        admin integer; 
    begin
    	select count(*) into encontrar from Departamento where dnumero = :new.trabajan_dno; 
    	if encontrar = 1 then 
    		if :new.superdni = 1 then 
    			insert into Supervisor values (:new.dni,:new.trabajan_dno);
    		controlarReplicDepartamento ('disable'); 
    			update Departamento 
    			set admin_dni = :new.dni where dnumero = :new.trabajan_dno; 
    		controlarReplicDepartamento ('enable'); 
    		else 
    			select admin_dni into admin from Departamento where dnumero = :new.trabajan_dno; 
    			insert into Supervisado values(:new.dni,admin);
    		end if; 
    	end if; 
    end;

    Ma fonction qui désactive le trigger B


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
     
    Create or replace procedure controlarReplicDepartamento (optcion varchar2)
    Is 
    	cadena varchar2(100); 
    Begin
    	cadena := 'Alter trigger replicDepartamento ' || optcion; 
    	execute immediate cadena; 
    End;
    Et voici ma procédure qui est appelé dans mon Trigger B, qui est incompatible avec mon trigger A

    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
     
     
    create or replace procedure despuesActualizDepartamento(dnumero_admin in integer, nuevoDnombre in varchar2, nuevoAdmin_dni in integer, antigoAdmin_dni in integer)
    Is
    	empleadoOradis integer:=0;
    	empleadoOragen integer:=0;
    Begin
    	update Departamento@lnkOradis set dnombre = nuevoDnombre where dnumero = dnumero_admin; 
    	if (nuevoAdmin_dni <> antigoAdmin_dni) then 
    		select count(*) into empleadoOradis from Empleado@lnkOradis where dni = antigoAdmin_dni;
    		select count(*) into empleadoOragen from Empleado where dni = antigoAdmin_dni;
     
    			-- Empleado Oragen
        		if (empleadoOragen = 1) then
     
    				-- Actualización del antigo administrador del departamento
    			update Empleado set sueldo = 8500, superdni = null where dni = antigoAdmin_dni;
                      	delete from Supervisor where superdni = antigoAdmin_dni; 
     
    				-- Actualización del nuevo administrador del departamento
    			update Empleado set sueldo = 12500, trabajan_dno = dnumero_admin, superdni = 1 where dni = nuevoAdmin_dni; 
    			insert into Supervisor values(nuevoAdmin_dni, dnumero_admin); 	
    			creaccionAdmin_trabajan_en('Trabajan_en',nuevoAdmin_dni, antigoAdmin_dni); 
     
    			-- Empleado Oradis				
                    elsif (empleadoOradis = 1) then
    				-- Actualización del antigo administrador del departamento
    			update Empleado@lnkOradis set sueldo = 8500, admin_dno = null, superdni = nuevoAdmin_dni where dni = antigoAdmin_dni; 
    				-- Actualización del nuevo administrador del departamento
    			update Empleado@lnkOradis set sueldo = 12500, admin_dno = dnumero_admin, trabajan_dno = dnumero_admin, superdni = nuevoAdmin_dni where dni = nuevoAdmin_dni; 
    			creaccionAdmin_trabajan_en('Trabajan_en@lnkOradis',nuevoAdmin_dni, antigoAdmin_dni); 
                    end if; 
     
            end if;
    End;
    L'instruction qui déclanche le problème dans le trigger actualizarEmpleadoOragen (Trigger A)

    c'est le update à l'intérieur sur la table Departamento.

    A ce moment il y a le Trigger replicDepartamento qui se déclancche quand on fait une mise à jour sur la table Departamento en apellant le procédure despuesActualizDepartamento, qui à l'intérieur fait un select sur la table Empleado est donc ça c'est interdit,, car c'est la table qui déclanche le trigger actulizarEmpleadoOragen.

    La context est un peu difficile à expliquer. je peux juste vous donner une vue partiel des relation qu'il y a dans mon système

    Les cardinalités sont les suivantes:
    un empleado peu administré un et un suel départemento (0,1)
    un empleado travaille dans un suel départamento (1,1)
    Un départamento est administré par un et un seul administrateur (1,1), qui est un empleado avec le superdni à 1.

    Désolé pour le code et les noms de variable, je fait actuellement un projet espagnol, je m'exuse aussi pour la grandeur de mon message.

    Mom problème est assez urgent, mon système tourne parfaitement, à par ce problème, et ce projet téoriquement je devais à la fin du week-end, je pense quelqu'un devra avoir la solution, il y a toujours des solutions que ne pense pas, en tout cas je vous en serais très reconnaissant, merci par avance

    dav79

  2. #2
    Membre du Club
    Homme Profil pro
    Développeur Back-End
    Inscrit en
    Avril 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Back-End

    Informations forums :
    Inscription : Avril 2006
    Messages : 113
    Points : 49
    Points
    49
    Par défaut
    Bonsoir à tous,

    Je r'explique mon problème plus brievement,

    Je voudrais désactiver mon trigger B quand mon trigger A s'exécute à un endroit nécessaire pour l'empécher qu'il appel le trigger B est que c'est possible oui ou non.

    Exemple de trigger A pour schématisé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
    create or replace trigger TriggerA 
    after insert on Empleado for each row 
     
    begin 
           controlTriggerB(disable); 
    .............................................................
           corps du triggerA, plusieurs conditions 
    ................................................................
          controlTriggerB(enable); 
    end;

    ça correspond à ma procédure controlarReplicDepartamento
    Si c'est possible comment il faut si prendre,

    Merci d'avance pour vos solutions


    dav79

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Février 2006
    Messages
    139
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Février 2006
    Messages : 139
    Points : 152
    Points
    152
    Par défaut
    Bonsoir,
    pour avoir vecu ce probleme de ping pong, c'est clair que c'est une torture.
    Perso je te conseillerais plutot de creer une variable globale(qui sera probablement une table suivant ton architecture) permettant d'indiquer si le corps du trigger doit etre executé ou pas:
    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 TriggerA 
    after INSERT ON Empleado FOR each row 
     
    begin 
           IF positionnement_du_triggerA_on then ; 
     
                      positionnement_du_triggerB_off; 
                      .............................................................
                      corps du triggerA, plusieurs conditions 
                      ................................................................
                      positionnement_du_triggerB_on; 
          END IF;
    end;
    Avec evidemment les memes controles sur le trigger B.

    Cdt

  4. #4
    Membre du Club
    Homme Profil pro
    Développeur Back-End
    Inscrit en
    Avril 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Back-End

    Informations forums :
    Inscription : Avril 2006
    Messages : 113
    Points : 49
    Points
    49
    Par défaut
    Merci beaucoup Kervoaz, pour ta réponse,

    Mais comment on s'y prend pour créer cette variable globale.
    Peut t'on désactiver un trigger dans un même trigger. Mais comment on fait car pour désactiver un trigger il faut faire un alter trigger est c'est une commande LDD qui n'est pas autorisé dans un trigger d'après ce que j'ai compris. Tu peux me donner un peu plus de détaille sur ta méthode, j'aimerai bien la mettre en oeuvre mais je n'ai pas bien compris. En fait j'ai juste compris qu'il faut créer un variable globale booléenne, qu'on va tester à l'intérieur du trigger.

    Est ce qu'on peut créer une variable booléenne sur un trigger pour l'activer ou le désactiver

    Merci pour tes réponses.

    dav79

  5. #5
    Membre du Club
    Homme Profil pro
    Développeur Back-End
    Inscrit en
    Avril 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Back-End

    Informations forums :
    Inscription : Avril 2006
    Messages : 113
    Points : 49
    Points
    49
    Par défaut
    Ok, par rapport à ton explication, ça revient un peu près au même je désactive le trigger 2, là ou c'est nécessaire puis je le réactive ensuite.

    Le problème c'est dans mon fonction j'utilise un commande execute immediate et cette commande fait automatiquement un commit. Et le trigger n'accepte pas les commit ou les rallback, donc je ne voix pas comment tu fait pour contourner ce problème, que tu t'iutilise un booléan pour activier ou désactiver un trigger, ce n'est pas le problème.

    Le problème c'est de le faire dans à l'intérieur d'un trigger.
    Peu tu me répondre rapidement, car effet je doit rendre mon projet demain ça m'arrangerait bien pour débloquer mon problème. Où si d'autres on la solution

    Merci d'avance

    dav79

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Février 2006
    Messages
    139
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Février 2006
    Messages : 139
    Points : 152
    Points
    152
    Par défaut
    Bonsoir,
    en fait ce n'est pas desactiver les triggers mais c'est mettre un test pour ne pas executer tout le code du trigger. Le plus simple:
    une table avec 2 colonnes t_lock(triggerA number(1), triggerB number(1))

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    create or replace triggerA is
    begin
       select triggerA into islock from t_lock;
        if (islock = 0) then
           update t_lock set triggerB=1;
           traitements declenchant triggerB;
           update t_lock set triggerB=0;
       end if;
    end;
    et la meme chose mais à l'inverse dans triggerB

    j'espere avoir compris ton probleme car j'ai un doute maintenant...

    Cdt

Discussions similaires

  1. [MySQL-5.6] Trigger qui déclenche une exception
    Par loustalet dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 18/04/2014, 21h13
  2. [ODBC] Problème de triggers qui ne se déclenche apparemment pas.
    Par polux31 dans le forum PHP & Base de données
    Réponses: 0
    Dernier message: 04/05/2011, 17h06
  3. Trigger qui ne se déclenche pas
    Par eowyn7 dans le forum Forms
    Réponses: 1
    Dernier message: 13/09/2007, 10h57
  4. Réponses: 2
    Dernier message: 14/06/2006, 15h04
  5. [trigger] ... qui ne se déclenche pas
    Par bozo dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 14/01/2004, 11h31

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