Вчера я работал над странной ошибкой в нашей производственной процедуре. Не удалось выполнить оператор
if v_cursor%isopen then
close v_cursor; -- here was an error
end if;
Немного покопавшись, я обнаружил, что проблема была в подпрограмме, которая открывала этот курсор. Я исправил ошибку, добавив выходной параметр sys _refcursor в подпрограмму. Чтобы прояснить ситуацию, рассмотрим следующий тестовый код:
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;
Если я пытаюсь запустить test_success
все ок, но на test_fail
я получаю сообщение
ORA-01001: Invalid cursor
Не могу найти никакой информации об этом. Кто-нибудь может объяснить, почему этот код не работает?
Версия Oracle:
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