Использовать курсор оракула в sys_refcursor
У меня есть пакет PL/SQL, который возвращает sys_refcursor на основе идентификатора, который вы передаете. Я хотел бы пройтись по некоторым идентификаторам и создать новый курсор ref с одним столбцом из исходного набора результатов, повторяемого для каждого идентификатора. (Вроде кросс-таблицы.) Очень упрощенная версия блока PL/SQL выглядит следующим образом:
create or replace package body dashboard_package is
procedure visits(RC in out sys_refcursor, IdNumber varchar2) as
BEGIN
OPEN RC FOR
select *
from (
select cat, cat_order, subcat, label_text
, trim(to_char(sum(v.current_month),'9,999,999,999')) current_month
, trim(to_char(sum(v.ly_month),'9,999,999,999')) ly_month
, trim(to_char(sum(v.ytd_tot),'9,999,999,999')) ytd_tot
, trim(to_char(sum(v.lytd_tot),'9,999,999,999')) lytd_tot
, trim(to_char(sum(v.ly_tot),'9,999,999,999')) ly_tot
from dashboard v
where v.id_number = IdNumber
group by cat_order, subcat, cat, label_text
union all
...
) a
order by cat_order, subcat;
END;
END;
Я думаю, если бы у меня было что-то подобное
create or replace procedure test_refcur is
refCursorValue SYS_REFCURSOR;
begin
dashboard_package.visits(refCursorValue,12345);
for cursrow in refCursorValue loop
dbms_output.put_line(cursrow.ytd_tot);
end loop;
end test_refcur;
работая, я мог бы взять это оттуда... есть мысли? Или, возможно, разъяснение по вопросу, который я должен задать.
1 ответ
Если вы входите с несколькими идентификаторами, тогда первым призом будет запуск только одного SQL-запроса для извлечения лота за один раз, используя массовую привязку для идентификаторов. Это, вероятно, потребует изменения dashboard_package.visits
или написание новой версии visits
процедура для принятия таблицы идентификаторов PL/SQL вместо одного идентификатора.
Если ваши руки связаны модификацией dashboard_package WRT, то вы можете написать конвейерную функцию, которая возвращает строки для набора идентификаторов:
-- create some helper types for the pipelined function
create type visitobj as object
(id number
,cat dashboard.cat%type
,cat_order dashboard.cat_order%type
,subcat dashboard.subcat%type
,label_text dashboard.label_text%type
,current_month varchar2(13)
,ly_month varchar2(13)
,ytd_tot varchar2(13)
,lytd_tot varchar2(13)
,ly_tot varchar2(13));
create type visittable as table of visitobj;
create or replace function test_refcur
return visittable deterministic pipelined is
refCursorValue SYS_REFCURSOR;
cat dashboard.cat%type;
cat_order dashboard.cat_order%type;
subcat dashboard.subcat%type;
label_text dashboard.label_text%type;
current_month varchar2(13);
ly_month varchar2(13);
ytd_tot varchar2(13);
lytd_tot varchar2(13);
ly_tot varchar2(13);
begin
for id in (/*iterate through the IDs*/) loop
dashboard_package.visits(refCursorValue, id);
loop
fetch refCursorValue into cat, cat_order, subcat, label_text,
current_month, ly_month, ytd_tot,
lytd_tot, ly_tot;
exit when refCursorValue%NOTFOUND;
pipe row (visitobj (id, cat, cat_order, subcat, label_text,
current_month, ly_month, ytd_tot,
lytd_tot, ly_tot));
end loop;
end loop;
return;
end test_refcur;
-- now you can simply do this:
SELECT * FROM TABLE(test_refcur);
(Конечно, "/*iterate through the IDs*/
"будет любым методом, который вы хотите использовать для сбора идентификаторов, для которых должна быть вызвана функция - например, это может быть таблица идентификаторов PL/SQL или, возможно, другой запрос).
Опять же, я бы подчеркнул, что "первый приз" заключается в том, чтобы вообще не выполнять эту дополнительную работу - просто dashboard_package.visits
это делает все это в одном SQL.
На заметку, trim(to_char(sum(v.ly_tot),'9,999,999,999'))
можно упростить до to_char(sum(v.ly_tot),'FM9,999,999,999')
, Кроме того, если вы используете формат 'FM9G999G999G999'
вместо этого он не будет зависеть от локали.