J'ai déjà posté ça, mais vu le manque de réaction je me demande si quelqu'un à lu et compris où est le problème.
Donc je vous proposé de reprendre la solution pour contourner l’erreur induite par la table en mutation (http://sgbd.developpez.com/oracle/ora-04091/):
Il y a une seule modification concernant le nombre de place disponible pour aller à Venise.
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
37
38
39
40
41
42
43
44
45
46 CREATE TABLE CLIENT( IDC INTEGER PRIMARY KEY , NOM VARCHAR2 (40) ) / CREATE TABLE VOYAGE( IDV INTEGER PRIMARY KEY , DESTINATION VARCHAR2 (40), MAXPLACE INTEGER , -- nombre total de places PLACEDISPO INTEGER ) -- nombre de places disponibles / CREATE TABLE INSCRIPTION( IDC INTEGER REFERENCES CLIENT(IDC), IDV INTEGER REFERENCES VOYAGE(IDV), DATERESERV DATE , CONSTRAINT INSCRIPTION_PK PRIMARY KEY (IDC, IDV) ) / INSERT INTO CLIENT(IDC, NOM) VALUES (1, 'DURAND'); INSERT INTO CLIENT(IDC, NOM) VALUES (2, 'DUBOIS'); INSERT INTO CLIENT(IDC, NOM) VALUES (3, 'DUGENOU'); COMMIT ; -- un seul place disponoble pour aller à VENISE INSERT INTO VOYAGE(IDV, DESTINATION, MAXPLACE, PLACEDISPO) VALUES (10, 'VENISE', 25, 1); INSERT INTO VOYAGE(IDV, DESTINATION, MAXPLACE, PLACEDISPO) VALUES (11, 'PRAGUE', 20, 0); COMMIT ; -- déclencheur qui n'interroge plus la table mutante CREATE OR REPLACE TRIGGER TRIG_INSCRIPTION BEFORE INSERT ON INSCRIPTION FOR EACH ROW DECLARE NB_DISPO INTEGER ; BEGIN SELECT PLACEDISPO INTO NB_DISPO FROM VOYAGE WHERE IDV=:NEW.IDV; IF NB_DISPO < 1 THEN DBMS_OUTPUT.PUT_LINE('Désolé, voyage complet'); ELSE UPDATE VOYAGE SET PLACEDISPO=PLACEDISPO - 1 WHERE IDV=:NEW.IDV; END IF ; END ; /
Ensuite j’ouvre une première session et j'ajoute une première inscription sans faire la validation (commit) :
Dans une autre session j'ajoute une deuxième inscription pour la même destination
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 -- DUGENOU aimerait bien aller à Venise : INSERT INTO INSCRIPTION(IDC, IDV, DATERESERV) SELECT 3, 10, TO_DATE(SYSDATE, 'DD/MM/YYYY') FROM DUAL ;
Enfin je valide dans chaque session (commit) et j’interroge la table du voyage :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 -- DUBOIS aimerait lui aussi aller à Venise : INSERT INTO INSCRIPTION(IDC, IDV, DATERESERV) SELECT 2, 10, TO_DATE(SYSDATE, 'DD/MM/YYYY') FROM DUAL ;
Autrement dit le trigger n'arrive pas à faire son boulot. Pour cella il faut reserver l'enregistrement de la table de voyage en mode pessimiste ou optimiste.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 SQL> SELECT * FROM voyage 2 ; IDV DESTINATION MAXPLACE PLACEDISPO ---------- ---------------------------------------- ---------- ---------- 10 VENISE 25 -1 11 PRAGUE 20 0
Il est intéressant de noter que la solution proposé par http://www.akadia.com/services/ora_m..._problems.html introduit le même type de problème.
Partager