Étrange erreur “Ora-01001 de curseur non Valide” dans la procédure
Hier, j'ai travaillé sur un bug étrange dans notre processus de production.
Échec de l'exécution sur la déclaration
if v_cursor%isopen then
close v_cursor; -- here was an error
end if;
Après quelques recherches dans j'ai découvert que le problème était dans le sous-programme qui a ouvert ce curseur. J'ai corrigé le bug en ajoutant le paramètre de sortie sys_refcursor dans le sous-programme. Afin de clarifier la situation envisager la suite de test de code:
procedure nested_test(test number,
p_cur out sys_refcursor)
is
procedure nested_procedure_fail is
begin
open p_cur for
select 1, 2, 3, 4
from dual
where 1 = 0;
end;
procedure nested_procedure_success(p_cur out sys_refcursor) is
begin
open p_cur for
select 1, 2, 3, 4
from dual
where 1 = 0;
end;
begin
if test = 1 then
nested_procedure_fail;
else
if test = 2 then
nested_procedure_success(p_cur => p_cur);
else
open p_cur for
select 6, 7, 8, 9
from dual
where 1 = 1;
end if;
end if;
end;
procedure test_fail is
v_cur sys_refcursor;
begin
nested_test(test => 1, p_cur => v_cur);
if v_cur%isopen then
close v_cur;
end if;
end;
procedure test_success is
v_cur sys_refcursor;
begin
nested_test(test => 2, p_cur => v_cur);
if v_cur%isopen then
close v_cur;
end if;
end;
Si j'essaie de le lancer test_success
tout est OK, mais sur test_fail
je reçois un message
ORA-01001: curseur non Valide
Je ne trouve aucune information à ce sujet. Quelqu'un peut-il expliquer pourquoi ce code ne fonctionne pas?
Oracle version:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for Solaris: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
OriginalL'auteur Axm | 2012-07-05
Vous devez vous connecter pour publier un commentaire.
Cela semble être un bug 7174888, ou au moins quelque chose qui y sont étroitement liées. La description de ce qui est "ORA-6504 soulevées lors de la sys_refcursor passé à une autre procédure", mais je peux le faire aussi si je change
test_fail
de faire un fetch:- Je obtenir
ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
.La solution de contournement dans le rapport de bug cures à la fois l'extraction et à proximité problème.
Le T&Cs ne me permet pas de reproduire des informations à partir de la prise en charge Oracle malheureusement. (Je ne devrais même pas avoir la solution de l'extrait, à y penser). Si vous ou vos Administrateurs de bases de données ont accès à la prise en charge Oracle vous pouvez rechercher le numéro du bogue.
Ok, merci beaucoup pour l'aide!
merci Alex, je pensais que j'étais en train de devenir folle! après tout, oracle est seulement un de plusieurs milliards de dollars de la société de sorte qu'il est prévu à partir de leurs utilisateurs à trouver une solution de contournement pour ces "petits" bugs".
OriginalL'auteur Alex Poole
Une question intéressante! Je voulais juste rajouter quelques choses.
Pour moi, la vraie question est en fonction de IS_OPEN pour déterminer si un curseur est valide ou pas. Oracle peut jeter INVALID_CURSOR pour de nombreuses raisons, et il est possible d'avoir un "open" curseur qui n'est pas valide. Semble raisonnable de supposer qu'un curseur ouvert doit être valide (et on peut donc en extraire des éléments ou d'effectuer d'autres opérations, comme une simple), mais ce n'est pas nécessairement le cas.
Par exemple, vous ne pouvez pas utiliser les variables curseur dans les appels de procédure distante (via dblinks). Ce même exemple, même à l'aide de Alex de la solution, serait un échec si l'ouverture a été appelée sur 1 db d'instance et de le récupérer sur un autre (si nested_test, n'importe quelle version, a été défini sur la db_A et a ensuite appelé à partir de db_B). Le test pour ISOPEN, cependant, serait toujours retourner VRAI, mais en essayant d'utiliser le curseur (fetch) serait un échec.
INVALID_CURSOR peut être soulevé pour d'autres raisons (comme aller au-delà de la max les curseurs ouverts, ou parfois l'ouverture d'un curseur et d'attendre un certain temps avant d'essayer de l'utiliser).
Tout ce que dit, il n'y a pas de "ISVALID" test que je connais. La meilleure approche de l'omi est d'ouvrir, d'extraire et de fermer les curseurs dans le même programme ou d'un sous-programme. La création d'une procédure dont la responsabilité est de simplement OUVRIR un curseur est un peu étrange pour moi (mais je suis sûr qu'il y a une raison), et peut provoquer dur à expliquer les enjeux (comme celui-ci). Si vous avez besoin d'un autre programme ouvrir un curseur pour vous, alors vous pourriez vouloir inclure le code qui récupère et, éventuellement, ferme le curseur dans un bloc anonyme et attraper le INVALID_CURSOR exception.
Juste mes divagations 😉
OriginalL'auteur tbone