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