我有这样一个包:
CREATE OR REPLACE PACKAGE PKG_EXAMPLE
IS
PROCEDURE SP_EXAMPLE_1 (inVal IN VARCHAR2, outCur OUT SYS_REFCURSOR);
PROCEDURE SP_EXAMPLE_2 (inVal IN VARCHAR2, outCur OUT SYS_REFCURSOR);
PROCEDURE SP_EXAMPLE_N (inVal IN VARCHAR2, outCur OUT SYS_REFCURSOR);
PROCEDURE SP_NON_CURSOR_EXAMPLE (inVal IN VARCHAR2, outVal OUT VARCHAR2);
END PKG_EXAMPLE;
CREATE OR REPLACE PACKAGE BODY PKG_EXAMPLE
AS
--for brevity, only showing one relevant procedure
PROCEDURE SP_EXAMPLE_N (inVal IN VARCHAR2, outCur OUT SYS_REFCURSOR)
IS
BEGIN
OPEN outCur FOR SELECT something FROM somewhere WHERE value = inVal;
END SP_EXAMPLE_N;
END PKG_EXAMPLE;
在运行时我循环浏览一些记录,我想动态调用此包中的过程(只有outCur OUT SYS_REFCURSOR
游标输出的过程)。出于演示的目的,我添加了SP_NON_CURSOR_EXAMPLE
来表明我可以这样称呼它:
DECLARE
outVal VARCHAR2(100);
BEGIN
FOR rec IN (SELECT 'SP_NON_CURSOR_EXAMPLE' as spName, inData FROM table_name) LOOP
EXECUTE IMMEDIATE 'CALL PKG_EXAMPLE.' || rec.spName || '(''' || rec.inData || ''', :myResult)'
USING OUT outVal;
END LOOP;
END;
这很有效。但是,如何对具有outCur OUT SYS_REFCURSOR
光标输出的过程执行此操作?我实际上并不需要光标结果或关心它们是什么,我只是想知道光标是否返回> 0结果。我想要这样的东西:
DECLARE
crs SYS_REFCURSOR;
cnt NUMBER;
BEGIN
FOR rec IN (SELECT spName, inData FROM table_name) LOOP
EXECUTE IMMEDIATE 'CALL PKG_EXAMPLE.' || rec.spName|| '(''' || rec.inData|| ''', :myResult)'
USING OUT crs;
cnt := crs%ROWCOUNT; -- this is what I need
END LOOP;
END;
但%ROWCOUNT
始终为零。我相信在检查它是否返回结果之前我必须FETCH
光标,但我不知道光标将返回哪些列或类型,因此我不确定我可以获取什么。
答案 0 :(得分:2)
可能不是最好的方法,但我找到了一个有效的解决方案......
DECLARE
crs SYS_REFCURSOR;
crsID NUMBER;
cnt NUMBER := 0;
BEGIN
FOR rec IN (SELECT spName, inData FROM table_name) LOOP
EXECUTE IMMEDIATE 'CALL PKG_EXAMPLE.' || rec.spName|| '(''' || rec.inData|| ''', :myResult)'
USING OUT crs;
crsID:= DBMS_SQL.TO_CURSOR_NUMBER(crs);
cnt := 0;
WHILE DBMS_SQL.FETCH_ROWS(crsID) > 0
LOOP
cnt := cnt + 1;
END LOOP;
END LOOP;
END;