Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 19/12/2007, 17h09   #1
Nouveau Membre du Club
 
Inscription : juillet 2005
Messages : 42
Détails du profil
Informations forums :
Inscription : juillet 2005
Messages : 42
Points : 31
Points : 31
Par défaut 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 (), 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
Gumpy est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/12/2007, 17h26   #2
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 319
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 319
Points : 5 837
Points : 5 837
Chaque fois quand j'arrive à faire PRAGMA_AUTONOMOUS_TRANSACTION et COMMIT dans un trigger je me dit que je suis bien dans les choux et donc je change de solution.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/12/2007, 17h53   #3
Expert Confirmé
 
Homme
Chef de projet en SSII
Inscription : janvier 2004
Messages : 2 866
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Chef de projet en SSII
Secteur : Conseil

Informations forums :
Inscription : janvier 2004
Messages : 2 866
Points : 3 448
Points : 3 448
Une des solutions envisageables est de mémoriser les matières mises à jour (tableau, table temporaire, ...) dans un trigger for each row

Puis dans un trigger after update global, de calculer les moyennes pour ces matières et de mettre à jour la table etudiant.

Si tu peux passer par une table temporaire, il me semble que c'est la meilleure solution car elle sera automatiquement remise à vide au commit. Le tableau devra être lui remis à zéro.
__________________
Un problème sans solution est un problème mal posé

Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.
plaineR est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2007, 09h32   #4
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
une vue matérialisée en ajoutant la colonne moyenne qui se rafraichie ON_COMMIT me parait beaucoup mieux indiquer qu'un trigger.

Eventuellement, tu peux peut-être créer une fonction en AUTONOMOUS TRANSACTION qui retourne la moyenne d'un éléve que tu appelleras dans ton trigger.
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2007, 09h53   #5
Expert Confirmé
 
Homme
Chef de projet en SSII
Inscription : janvier 2004
Messages : 2 866
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Chef de projet en SSII
Secteur : Conseil

Informations forums :
Inscription : janvier 2004
Messages : 2 866
Points : 3 448
Points : 3 448
Citation:
Envoyé par orafrance Voir le message
Eventuellement, tu peux peut-être créer une fonction en AUTONOMOUS TRANSACTION qui retourne la moyenne d'un éléve que tu appelleras dans ton trigger.
Non cela ne marchera pas puisque avec ta fonction en autonomous_transaction tu verras la valeur de la note avant la mise à jour.
__________________
Un problème sans solution est un problème mal posé

Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.
plaineR est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2007, 09h56   #6
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
tu peux passer old et new en paramètre pour remplacer la valeur dans la fonction éventuellement
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2007, 10h45   #7
Nouveau Membre du Club
 
Inscription : juillet 2005
Messages : 42
Détails du profil
Informations forums :
Inscription : juillet 2005
Messages : 42
Points : 31
Points : 31
Merci pour tous vos conseils! Je vais essayer tout ça
Gumpy est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 07h53.


 
 
 
 
Partenaires

Hébergement Web