游标名称将作为varchar2传入,并且游标本身与过程存在于同一个包中。
只给出名称(而不是游标引用)是否可以访问游标并循环通过它?
如果这需要使用"立即执行"或类似的,这不是不可能的......(尽管我不太清楚这是如何工作的,但我认为它宣称的任何东西一旦完成就会超出范围)。
提前道歉,这似乎对我来说应该是显而易见的,但我是空白的。
答案 0 :(得分:1)
考虑到这一点,我认为你的方式是错误的。我将每个“游标”的所有结果联合起来,然后使用“游标名称”消除所有不需要的行(优化程序应该优化掉的行),这样你才能得到你想要的行。像
这样的东西CREATE OR REPLACE PROCEDURE DO_SOMETHING(pin_Cursor_name IN VARCHAR2)
IS
CURSOR csrFruits IS
SELECT UPPER(pin_Cursor_name) AS FRUIT_TYPE,
VARIETY_NAME,
COLOR,
SIZE,
TARTNESS_RATING,
NULL AS FUZZ_LENGTH,
ROOTSTOCK,
NULL AS PEEL_THICKNESS
FROM APPLES
WHERE pin_Cursor_name = 'apples'
UNION ALL
SELECT UPPER(pin_Cursor_name) AS FRUIT_TYPE,
VARIETY_NAME,
COLOR,
SIZE,
NULL AS TARTNESS_RATING,
FUZZ_LENGTH,
NULL AS ROOTSTOCK,
NULL AS PEEL_THICKNESS
FROM PEACHES
WHERE pin_Cursor_name = 'peaches'
UNION ALL
SELECT UPPER(pin_Cursor_name) AS FRUIT_TYPE,
VARIETY_NAME,
COLOR,
SIZE,
NULL AS TARTNESS_RATING,
NULL AS FUZZ_LENGTH,
NULL AS ROOTSTOCK,
PEEL_THICKNESS
FROM KUMQUATS
WHERE pin_Cursor_name = 'kumquats'
UNION ALL
SELECT UPPER(pin_Cursor_name) AS FRUIT_TYPE,
VARIETY_NAME,
'GREEN' AS COLOR,
SIZE,
NULL AS TARTNESS_RATING,
FUZZ_LENGTH,
ROOTSTOCK,
NULL AS PEEL_THICKNESS
FROM KIWIS
WHERE pin_Cursor_name = 'kiwis';
BEGIN
FOR aRow IN csrFruits LOOP
DBMS_OUTPUT.PUT_LINE(pin_Cursor_name || ' - ' ||
aRow.VARIETY_NAME || ', ' ||
aRow.COLOR || ', ' ||
aRow.SIZE);
END LOOP;
END DO_SOMETHING;
所以这里我们有一个游标,它将根据输入参数从四个不同的表(APPLES,PEACHES,KUMQUATS和KIWIS)中的一个读取。我们的想法是让每个子查询返回一个具有相同“形状”的行集,为每个列添加NULL AS XXX
,而单个子查询不提供这些行。
祝你好运。
答案 1 :(得分:0)
你原来的问题陈述有点模糊,我不清楚你有什么约束以及“其他系统”期望作为回报值。你也可能有一个XY-problem,所以@bobjarvis的答案也可能有一个有效点。
这里的关键问题是在PL / SQL中无法将explicit cursor转换为cursor variable。因此,以下“简单”解决方案是不可能的:
-- pseudo PL/SQL code
cursor cur_a ...
cursor cur_b ...
function get_cursor(p_cur_name varchar2) return sys_refcursor is
v_cur sys_refcursor;
begin
execute immediate 'open v_cur for p_cur_name';
return v_cur;
end;
v_cur := get_cursor('cur_b');
在下面的示例包中,我假设所有游标都具有相同的结果集结构。我很懒,并使用弱光标变量,即使我应该使用强大的变量。包裹代码应该很容易理解。
至少还有一个可能对您有用的变体 - 批量收集数据到集合并使用其他子例程处理集合。 print(varchar2)
下面只展示了如何使用dbms_output.put_line
“动态”打开迭代关闭游标。
create or replace package so48 is
cursor cur_a is
select 'A1' as val, 1 as id from dual union all
select 'A2' as val, 2 as id from dual union all
select 'A3' as val, 3 as id from dual
;
cursor cur_b is
select 'B1' as val, 4 as id from dual union all
select 'B2' as val, 5 as id from dual union all
select 'B3' as val, 6 as id from dual
;
function get_cursor(p_cur_name in varchar2) return sys_refcursor;
procedure print(p_cur in sys_refcursor);
procedure print(p_cur_name in varchar2);
end;
/
show errors
create or replace package body so48 is
function get_cursor(p_cur_name in varchar2) return sys_refcursor is
v_cur sys_refcursor;
begin
case
when p_cur_name = 'A' then
open v_cur for
select 'A1' as val, 1 as id from dual union all
select 'A2' as val, 2 as id from dual union all
select 'A3' as val, 3 as id from dual
;
when p_cur_name = 'B' then
open v_cur for
select 'B1' as val, 4 as id from dual union all
select 'B2' as val, 5 as id from dual union all
select 'B3' as val, 6 as id from dual
;
else
null;
end case;
return v_cur;
end;
procedure print(p_cur in sys_refcursor) is
v_val varchar2(32767);
v_id number;
begin
loop
fetch p_cur into v_val, v_id;
exit when p_cur%notfound;
dbms_output.put_line('(val = ' || v_val || ')(id = ' || v_id || ')');
end loop;
end;
procedure print(p_cur_name in varchar2) is
plsql_compilation_error exception;
pragma exception_init(plsql_compilation_error, -6550);
v_cur_name constant varchar2(32767) := 'so48.' || p_cur_name;
v_plsql constant varchar2(32767) :=
q'[declare
v_val varchar2(32767);
v_id number;
begin
open ]' || v_cur_name || q'[;
loop
fetch ]' || v_cur_name || q'[ into v_val, v_id;
exit when ]' || v_cur_name || q'[%notfound;
dbms_output.put_line('(val = ' || v_val || ')(id = ' || v_id || ')');
end loop;
close ]' || v_cur_name || q'[;
end;]';
begin
execute immediate v_plsql;
exception
when plsql_compilation_error then
dbms_output.put_line('PL/SQL compilation error');
end;
end;
/
show errors
运行示例
SQL> exec so48.print(so48.get_cursor('A'))
(val = A1)(id = 1)
(val = A2)(id = 2)
(val = A3)(id = 3)
PL/SQL procedure successfully completed.
SQL> exec so48.print('cur_b')
(val = B1)(id = 4)
(val = B2)(id = 5)
(val = B3)(id = 6)
PL/SQL procedure successfully completed.
SQL>