真的需要有关Ref Cursor的帮助。我有一个存储过程GET_PERSONROLES具有参数类型引用游标。我只是想手动将这个引用游标傀儡,就像在refcursor中插入一行一样。 我可以通过循环将行插入refcursor吗? 提前谢谢。
该程序取决于此公开声明的类型:
create or replace package types
as
type cursorTypePersonRole is ref cursor;
end;
这是我的伪代码
create or replace PROCEDURE GET_PERSONROLES
(
P_CURSOR IN OUT types.cursorTypePersonRole
) AS
REFCUR SYS_REFCURSOR;
TYPE REFTABLETYPE IS RECORD (
IS_MANAGER_LEVEL1 VARCHAR2(1),
IS_MANAGER_LEVEL2 VARCHAR2(1)
);
TYPE TABLETYPE IS TABLE OF REFTABLETYPE;
PERSONROLES_TABLETYPE TABLETYPE;
BEGIN
--calls another stored proc to populate REFCUR with data without problem
MY_STOREDPROC('12345', REFCUR);
LOOP
FETCH REFCUR BULK COLLECT INTO PERSONROLES_TABLETYPE;
EXIT WHEN PERSONROLES_TABLETYPE.COUNT = 0;
FOR indx IN 1 .. PERSONROLES_TABLETYPE.COUNT
LOOP
-- I'm able to query perfectly the values of IS_MANAGER_LEVEL1 and IS_MANAGER_LEVEL 2
-- I'm aware that the below codes are wrong
-- However this means I wanted to insert these values to a row of the cursor if possible
-- Do some logic to know what data will be assigned in the row.
if PERSONROLES_TABLETYPE(indx).IS_MANAGER_LEVEL1 = 'Y' then
P_CURSOR := <DO SOME LOGIC AND ASSIGN THE VALUE TO THE ROW>
end if;
if PERSONROLES_TABLETYPE(indx).IS_MANAGER_LEVEL2 = 'Y' then
P_CURSOR := <DO SOME LOGIC AND ASSIGN THE VALUE TO THE ROW>
end if;
END LOOP;
END LOOP;
CLOSE REFCUR;
END GET_PERSONROLES;
答案 0 :(得分:3)
引用游标不是变量:它是指向结果集的指针,该结果集由读取它的行为消耗。结果集本身是不可变的。
不可变性是有道理的,因为它反映了Oracle强调读取一致性。
生成您想要的输出的最简单方法是创建SQL类型
open P_CURSOR for
select IS_MANAGER_LEVEL1,
IS_MANAGER_LEVEL2
from table ( PERSONROLES_TABLETYPE );
这将在12c中起作用;在早期版本中使用table()
这样的调用,您可能需要将REFTABLETYPE
和TABLETYPE
声明为SQL类型(而不是PL / SQL)。
“确定现在编辑”
唉,你的要求仍然不明确。您没有给我们输出引用光标的结构或显示您想要进行的其他处理。
然而,鉴于你的问题的标题,让我们猜一下。所以:
create or replace PROCEDURE GET_PERSONROLES ( P_CURSOR IN OUT types.cursorTypePersonRole) AS
REFCUR SYS_REFCURSOR;
TYPE REFTABLETYPE IS RECORD (IS_MANAGER_LEVEL1 VARCHAR2(1),
IS_MANAGER_LEVEL2 VARCHAR2(1));
TYPE TABLETYPE IS TABLE OF REFTABLETYPE;
PERSONROLES_TABLETYPE TABLETYPE;
personrole_rec PersonRole%rowtype;
type personrole_nt is table of PersonRole%rowtype;
personroles_recs personrole_nt := new personrole_nt() ;
BEGIN
MY_STOREDPROC('12345', REFCUR);
FETCH REFCUR BULK COLLECT INTO PERSONROLES_TABLETYPE;
FOR indx IN 1 .. PERSONROLES_TABLETYPE.COUNT LOOP
/* in the absence of requirements I'm just making some stuff up */
if PERSONROLES_TABLETYPE(indx).IS_MANAGER_LEVEL1 = 'Y' then
personrole_rec.whatever1 := 'something';
else
personrole_recc.whatever1 := null;
end if;
if PERSONROLES_TABLETYPE(indx).IS_MANAGER_LEVEL2 = 'Y' then
personrole_rec.whatever2 := 'something else';
else
personrole_recc.whatever2 := null;
end if;
if personrole_rec.whatever1 is not null
or personrole_rec.whatever2 is mot null then
personroles_recs.exend();
personroles_recs(personroles_recs.count()) := personroles_rec;
end if;
END LOOP;
CLOSE REFCUR;
open p_cursor for
select * from table ( personroles_recs );
END GET_PERSONROLES;
此代码使用第二个集合来存储所需的输出。与您的代码一样,它会读取填充的集合并评估每行的属性。如果一个值表示它在行类型变量中设置属性的条件。如果设置了一个或两个属性,则会在第二个集合中填充新行。在过程结束时,它使用第二个集合上的table()
函数调用打开引用游标。
请注意,您不需要嵌套循环:您没有使用LIMIT子句,因此您的编码器会将整个光标一次性读入集合中。
实施的规则可能不完全符合您的要求(因为您没有准确解释您想要的内容),但这应该给您一般的想法。
请注意,根据<DO SOME LOGIC AND ASSIGN THE VALUE TO THE ROW>
确切掩盖的处理方式,更简单的方法仍然可行:
open P_CURSOR for
select case when IS_MANAGER_LEVEL1 = 'Y' then 'YES' else 'NO' end,
case when IS_MANAGER_LEVEL2 = 'Y' then 'YES' else 'NO' end
from table ( PERSONROLES_TABLETYPE );