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 :
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.
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'
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
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 Create or replace procedure controlarReplicDepartamento (optcion varchar2) Is cadena varchar2(100); Begin cadena := 'Alter trigger replicDepartamento ' || optcion; execute immediate cadena; End;
L'instruction qui déclanche le problème dans le trigger actualizarEmpleadoOragen (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;
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
Partager