使用引用游标输出动态执行存储过程
Dynamically execute a stored procedure with reference cursor output
我有这样一个包裹:
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
游标输出的过程,我该如何做呢?我实际上并不需要游标结果或关心它们是什么,我只是想知道游标是否 returned > 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
游标才能检查它是否 returned 结果,但我不知道游标将 return 是什么列或类型,所以我不知道确定我能拿到什么。
可能不是最好的方法,但我找到了一个可行的解决方案...
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;
我有这样一个包裹:
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
游标输出的过程,我该如何做呢?我实际上并不需要游标结果或关心它们是什么,我只是想知道游标是否 returned > 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
游标才能检查它是否 returned 结果,但我不知道游标将 return 是什么列或类型,所以我不知道确定我能拿到什么。
可能不是最好的方法,但我找到了一个可行的解决方案...
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;