使用引用游标输出动态执行存储过程

时间:2016-01-22 19:18:56

标签: oracle plsql oracle12c

我有这样一个包:

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光标,但我不知道光标将返回哪些列或类型,因此我不确定我可以获取什么。

1 个答案:

答案 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;