Seltsame Fehlermeldung "Ora-01001 Ungültiger cursor" im Verfahren
Gestern arbeitete ich an einem seltsamen Fehler in unserer Produktions-Verfahren.
Fehler beim ausführen auf Anweisung
if v_cursor%isopen then
close v_cursor; -- here was an error
end if;
Nachdem einige Graben in die ich entdeckte, dass das problem war in Unterprogramm, das die Eröffnung dieses cursor. Ich behoben durch hinzufügen von output-parameter sys_refcursor im Unterprogramm. Zu klären situation betrachten Sie folgenden test-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;
Wenn ich versuche zu laufen test_success
ist alles OK, aber auf test_fail
ich eine Nachricht erhalten,
ORA-01001: Ungültiger cursor -
Ich kann nicht finden alle Informationen über dieses. Kann mir jemand erklären, warum dieser code nicht?
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
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese erscheint Fehler 7174888, oder zumindest etwas, was eng damit zusammenhängen. Die Beschreibung für die, die 'ORA-6504 ausgelöst, wenn sys_refcursor übergeben, um ein anderes Verfahren', aber ich kann machen, was passiert, wenn ich ändern
test_fail
zu tun fetch:Bekomme ich
ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
.Den workaround in die bug-report-Kuren sowohl die fetch-und close problem.
Eine interessante Frage! Wollte nur hinzufügen, ein paar Dinge.
Mir, das eigentliche Problem ist in Abhängigkeit von der IS_OPEN um festzustellen, ob ein cursor gültig ist oder nicht. Oracle werfen kann INVALID_CURSOR für viele Gründe, und es ist möglich, einen "öffnen" - cursor, der nicht gültig ist. Scheint vernünftig anzunehmen, dass ein geöffneter cursor muss gültig sein (und wir können daher Holen von ihm, oder führen Sie andere Operationen, wie eine einfache in der Nähe), aber dies ist nicht notwendigerweise der Fall.
Beispielsweise können Sie nicht verwenden Sie cursor-Variablen, die in remote procedure calls (via dblinks). Das gleiche Beispiel auch mit Alex umgehen, scheitern würden, wenn die offen genannt wurde, am 1-db-instance und der Abruf auf einen anderen (wenn nested_test, jede version, definiert wurde db_A und rief dann aus db_B). Der test für ISOPEN, würde aber immer noch TRUE zurück, aber dann zu versuchen, verwenden Sie die cursor - (fetch) scheitern würde.
INVALID_CURSOR ausgelöst werden können, aus anderen Gründen (wie wird über die max open cursors, oder manchmal einen cursor geöffnet und warten eine Weile, bevor Sie versuchen, es zu benutzen).
Alles, was gesagt, es gibt keine "ISVALID" - test, den ich kenne. Der beste Ansatz imo ist das öffnen, abrufen und schließen von Cursorn innerhalb der gleichen Programm oder Unterprogramm. Erstellen einer Prozedur, deren Aufgabe ist es, ÖFFNEN Sie einfach ein cursor ist ein bisschen seltsam auf mich (aber ich bin sicher, dass gab es aus irgendeinem Grund), und kann dazu führen, schwer zu erklären, Fragen (wie diese). Wenn Sie ein anderes Programm öffnen einen cursor für Sie, dann möchten Sie vielleicht, schließen Sie den code holt und irgendwann schließt sich der cursor in einen anonymen block und fangen die INVALID_CURSOR-Ausnahme aus.
Nur mein Geschwafel 😉