Bonjour,
Je suis sous Oracle 10gR2.
J'ai un problème avec un bout de code en PL/SQL qui plante avec l'erreur ORA-01002 : fetch out of sequence.
Après recherche, il apparaitrait que cette erreur se produit dans un des 3 cas suivant :Le code a l'aspect suivant: (dans un package)
- Fetch d'un curseur alors que toutes les lignes ont été lues
- Commit à l'intérieur d'une boucle FOR LOOP sur un curseur ouvert en mode FOR UPDATE
- Re-bind de variable d'une requête SQL et fetch sans rééxecuter la requête
La procédure PROC_INSERT_TEMP est une procédure autonome (PRAGMA AUTONOMOUS_TRANSACTION) qui fait une insertion dans une table et un commit.
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 PROCEDURE MAPROC IS CURSOR C1 IS SELECT ... FROM TABLE_DES_VOYAGES M WHERE M.KEY = MaVariableKey AND EXISTS (SELECT 1 FROM TABLE_DES_TRAVAUX T WHERE T.KEY = M.KEY AND T.STATUS <> 'X') FOR UPDATE; R1 C1%ROWTYPE; CURSOR C2 IS SELECT ... FROM TABLE_DES_TRAVAUX WHERE KEY = R1.KEY FOR UPDATE; CURSOR C3 IS SELECT ... FROM TABLE_QUELCONQUE WHERE << condition >>; R3 C3%ROWTYPE; BEGIN FOR FORTDV IN C1 LOOP R1.KEY = FORTDV.KEY; UPDATE TABLE_DES_VOYAGES SET CHAMP = Calcul WHERE CURRENT OF C1; PROC_INSERT_TEMP; -- procédure autonome OPEN C3; LOOP FETCH C3 INTO R3; EXIT WHEN C3%NOTFOUND; -- calcul sur R3 END LOOP; CLOSE C3; FOR R2 IN C2 LOOP UPDATE TABLE_DES_TRAVAUX SET CHAMP = Calcul WHERE CURRENT OF C2; END LOOP; END LOOP; EXCEPTION ... END;
A la vue du code, j'ai d'abord cherché la présence d'un COMMIT qui agirait dans un des 2 FOR LOOP. Malheureusement, le seul présent est dans la procédure autonome, et j'ai effectué plusieurs tests qui m'ont montré que dans ce cas, il n'y a pas d'erreur.
J'ai ensuite envisagé une erreur sur le fetch du curseur C3, mais là aussi, des tests m'ont montré que j'ai beau faire plus de fetch que le curseur a de lignes, je ne tombe pas en erreur. Tout au plus, ma variable receptrice vaut NULL et j'ai C3%FOUND = FALSE.
Donc, à ce stade, je suis bloqué aux constatations suivantes :Je ne peux hélas pas débugger ce bout de code, ni rejouer le package car cela se passe en production. Avez-vous des idées sur le problème ?
- Le cas du fetch alors que toutes les lignes ont déjà été lues ne semble pas être le problème (d'ailleurs, je n'arrive pas à reproduire cette erreur)
- Le cas du commit dans une boucle FOR LOOP avec un curseur FOR UPDATE n'est pas le problème de manière quasiment certaine
- J'avoue ne pas comprendre ce que veut dire le rebind ? D'ailleurs, je remets la définition en anglais au cas où ma traduction soit hasardeuse : Rebinding any placeholders in the SQL statement, then issuing a fetch before reexecuting the statement
Partager