ОК, поэтому краткий ответ от Oracle: «не может быть сделано!»
Краткий ответ от меня: «Да - как Oracle остановит меня! Так что да, вы можете ..... но вам нужно быть подлым ... о да, и есть "но" или два ... на самом деле ... тьфу! "
Итак, как вы можете передать свой явный курсорпо ссылке?Вложив его в другой курсор с помощью конструкции CURSOR ()!
например)
CREATE OR REPLACE package CFSDBA_APP.test_Cursor
as
function get_cursor(ed_id number) return sys_refcursor;
end;
/
CREATE OR REPLACE package body CFSDBA_APP.test_Cursor
as
function get_cursor(ed_id number) return sys_refcursor
is
test_Cur sys_refcursor;
cursor gettest is
select CURSOR( -pass our actual query back as a nested CURSOR type
select ELCTRL_EVNT_ELCTRL_DISTRCT_ID,
ELECTORAL_DISTRICT_ID,
ELECTORAL_EVENT_ID
from ELCTRL_EVNT_ELCTRL_DISTRCT
where electoral_District_id = ed_id)
from dual;
begin
open gettest;
fetch gettest into test_Cur;
return test_Cur;
end;
end;
/
Так в чем же проблема с этим решением?Это утечка!Внешний курсор gettest никогда не закрывается, потому что мы не закрываем его, и клиент будет закрывать только ссылку на вложенный курсор, который был выбран для них, а не основной курсор.И мы не можем закрыть его автоматически, потому что закрытие родителя заставит закрыть вложенный курсор, который вы вернули по ссылке, - и вполне вероятно, что клиент не использовал его.
Поэтому мы должны уйтикурсор, открытый для возврата вложенного курсора.
И если пользователь попытается снова вызвать get_Cursor с новым значением ed_id, он обнаружит, что сохранение сеанса в пакете означает, что дескриптор курсора все еще находится вuse и возникнет ошибка.
Теперь мы могли бы это исправить, сначала проверив и закрыв явный курсор:
if gettest%isopen then
close gettest;
end if;
open gettest;
fetch gettest into test_Cur;
return test_Cur;
Но все же - что если пользователь никогда не вызовет это снова?Как долго Oracle будет собирать курсор?И сколько пользователей, выполняющих, сколько сеансов, вызывающих, сколько функций, использующих эту конструкцию, оставят открытыми курсоры после того, как они закончили с ними?Лучше рассчитывать на издержки huuuuuge, чтобы все эти открытые курсоры лежали без дела!
Нет, вам нужно, чтобы пользователи сделали обратный вызов, чтобы явно закрыть его, иначе вы бы засорили базу данных.Но для этого потребуется изменить область действия явного курсора, чтобы обе функции могли получить к нему доступ: поэтому нам нужно сделать это в области действия пакета, а не в области действия функции
CREATE OR REPLACE package CFSDBA_APP.test_Cursor
as
function get_cursor(ed_id number) return sys_refcursor;
function close_cursor return sys_refcursor;
end;
/
CREATE OR REPLACE package body CFSDBA_APP.test_Cursor
as
cursor l_gettest(p_ed_id in number) is
select CURSOR(
select ELCTRL_EVNT_ELCTRL_DISTRCT_ID, ELECTORAL_DISTRICT_ID, ELECTORAL_EVENT_ID
from ELCTRL_EVNT_ELCTRL_DISTRCT
where electoral_District_id = p_ed_id)
from dual;
function get_cursor(ed_id number) return sys_refcursor
is
l_get_Cursor sys_refcursor;
begin
open l_gettest (ed_id);
fetch l_gettest into l_get_Cursor;
return l_get_cursor;
end;
function close_cursor return sys_refcursor
is
begin
if l_gettest%isopen then
close l_gettest;
end if;
return pkg_common.generic_success_cursor;
end;
end;
/
ОК, чтобы устранить утечку.За исключением того, что это стоило нам обхода по сети вместо жесткого анализа ... о, подождите, а также за исключением того, что встраивание переменной связывания в явный курсор, объявленный на этом уровне, вероятно, вызовет проблемы со своей областью видимости, по этой причине мыхотел сделать это в первую очередь!
О, а в среде пула сеансов два пользователя могут наступать на курсоры друг друга?Если они не очень заботятся о выполнении open-fetch-close перед возвратом сеанса в пул - мы можем получить действительно интересные (и невозможные для отладки) результаты!
А сколько выдоверяете разработчикам клиентского кода быть слишком усердными в этом?Да, я тоже.
Итак, краткий ответ: да, с некоторой подлостью это можно сделать, несмотря на то, что Oracle говорит, что не может.
Лучший ответ: но, пожалуйста, дона«т!Дополнительное круговое обращение и возможность утечек памяти и ошибок клиентского кода, вызывающих проблемы с данными, делают это очень пугающим предложением.