【问题标题】:Dynamically execute a stored procedure with reference cursor output使用引用游标输出动态执行存储过程
【发布时间】:2016-01-26 01:11:23
【问题描述】:

我有一个这样的包裹:

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 游标才能检查它是否返回结果,但我不知道游标将返回哪些列或类型,所以我不确定我可以获取什么。

【问题讨论】:

    标签: oracle plsql oracle12c


    【解决方案1】:

    可能不是最好的方法,但我找到了一个可行的解决方案...

    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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-25
      • 2012-05-10
      • 2017-07-19
      • 2010-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多