Pb Tables Mutantes sur Trigger et Autonomous_Transaction
Bonjour,
J'ai des soucis avec un problème de table mutante, naturellement j'ai fait des recherches sur google et j'ai lu attentivement le tutoriel http://sgbd.developpez.com/oracle/ora-04091/
J'ai simplifié mon problème en ce que je vous expose ci-après pour faciliter la compréhension, mais il s'agît également de ce que je suis en train de tester.
Mes Tables :
etudiant (id, nom, moyenne);
matiere (id, note, id_etudiant);
Je souhaiterai calculer la moyenne d'un étudiant à chaque fois qu'une note est modifiée (imaginons que toutes les notes dont j'ai besoin sont déjà insérées et initialisées). Pour cela on m'impose l'utilisation d'un Trigger.
Mon Trigger sera appelé lors de l'utilisation d'un UPDATE de cette forme :
Code:
1 2
|
UPDATE matiere SET note = 20 WHERE id = xx; |
xx correspondant à l'id en base de la note modifiée.
Voici le Trigger :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
create or replace
TRIGGER TEST_TG
AFTER UPDATE ON matiere
REFERENCING NEW as n
FOR EACH ROW
DECLARE
idE integer;
moyenne_generale number;
BEGIN
SELECT :n.id_etudiant INTO idE FROM dual;
SELECT AVG(note) INTO moyenne_generale
FROM matiere
WHERE id_etudiant = idE;
UPDATE etudiant
SET moyenne = moyenne_generale
WHERE id = idE;
END; |
C'est donc là qu'apparait mon problème de table mutante, faisant un SELECT sur une table au moment où elle est modifiée.
1ere remarque : Dans le tuto Développez.com, la méthode "E-4. Je suis grand, c'est moi qui gère" me fait sortir du Trigger sans modifier la moyenne.
2eme remarque : Je préfère ne pas avoir recours aux autres méthodes de ce tutoriel (pour le moment...) pour diverses contraintes auxquelles je suis soumis.
J'ai eu accès à un code semblable au mien qui marche en utilisant une directive PRAGMA AUTONOMOUS_TRANSACTION, de plus après des recherches cette solution semble effectivement marcher, et elle m'intéresse très fortement.
J'ai donc modifié mon Trigger comme suit :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
create or replace
TRIGGER TEST_TG
AFTER UPDATE ON matiere
REFERENCING NEW as n
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
idE integer;
moyenne_generale number;
BEGIN
SELECT :n.id_etudiant INTO idE FROM dual;
SELECT AVG(note) INTO moyenne_generale
FROM matiere
WHERE id_etudiant = idE;
UPDATE etudiant
SET moyenne = moyenne_generale
WHERE id = idE;
COMMIT;
END; |
Et là arrive ma véritable question : ce trigger a les mêmes effets qu'un BEFORE UPDATE, c'est à dire que la moyenne calculée est celle qui était vraie avant la modification d'une des notes.
J'ai essayé de déplacer le COMMIT dans le trigger, et de le mettre partout dans le trigger (:mrgreen:), même résultat.
J'aimerais donc savoir si il y avait une explication à ce phénomène et si je pouvais y remédier (en gardant la solution des transactions autonomes qui semble marcher dans le même cas de figure sur d'autres applications...).
Maintenant si vous me déconseillez cette méthode (même si jamais j'arrivai à la faire marcher), j'aimerai également savoir pourquoi (sachant qu'il s'agît d'une application multi-thread)
Merci d'avance pour vos conseils :D