【问题标题】:how to implement refcursor when there is "execute immediate" in oracle?oracle中有“立即执行”时如何实现refcursor?
【发布时间】:2019-11-24 13:36:17
【问题描述】:

我之前使用过sys_refcursor来返回select语句的数据。但是,我在这里使用execute immediate,所以我无法在execute immediate语句中使用sys_refcursor。

以前我是这样做的

R_C OUT SYS_REFCURSOR //refcursor
    OPEN R_C FOR  //it used to handle the return of all select statement
    SELECT * FROM table_name;

但是,我今天尝试立即执行,我无法打印 select 语句的数据。 所以,按照我的尝试是:

CREATE OR REPLACE PROCEDURE OT.check_data(DATA1 number,R_C OUT SYS_REFCURSOR)
    IS 
    vquery long;
    BEGIN
    vquery :='select * from ot.employee ';
    if data1 = 10 then
    vquery := vquery||' where deptno in (10)';
    else
     vquery := vquery||' where deptno in (20,30)';
    end if;
    execute immediate vquery;
    END;
    /

   exec OT.check_data(10); 

程序运行正常,但我看不到 select 语句的数据。如何在控制台中显示 execute immediate 的数据?我正在使用 toad。

【问题讨论】:

    标签: oracle plsql oracle11g


    【解决方案1】:

    您可以通过执行以下操作为动态构建的 SELECT 语句返回 SYS_REFCURSOR:

    CREATE OR REPLACE PROCEDURE OT.check_data(DATA1    number,
                                              R_C OUT  SYS_REFCURSOR)
    IS 
      vQuery VARCHAR2(32767);
      rc     SYS_REFCURSOR;
    BEGIN
      vQuery :='select * from ot.employee ';
    
      if data1 = 10 then
        vQuery := vQuery ||' where deptno in (10)';
      else
        vQuery := vQuery ||' where deptno in (20,30)';
      end if;
    
      OPEN rc FOR vQuery;
      R_C := rc;
    END;
    

    我强烈建议您不要使用 LONG 数据类型。这已被弃用多年,而今天(tm)甲骨文最终将放弃对它的支持。要么使用 VARCHAR2,在这种情况下就足够了,要么使用 CLOB。

    【讨论】:

    • [警告] ORA-24344:编译错误 6/1 PLS-00103 成功:在预期以下情况之一时遇到符号“BEGIN”::=。 (@% ; 非空范围默认字符符号“;”被替换为“BEGIN”继续。(1:0): 警告: 已编译但有编译错误
    • 在 SYS_REFCURSOR 行中遗漏了一个分号。
    • 我尝试使用 VARIABLE R_C REFCURSOR 执行该过程;执行 OT.check_data(10,R_C);但它是说我 PLS-00201:必须声明标识符“R_C”。我犯了什么错误?
    • VARIABLE 引用必须以冒号开头。所以:R_C 而不是R_C
    【解决方案2】:

    您可以为它创建一个简单的过程。

    CREATE OR REPLACE PROCEDURE OT.check_data(DATA1    number,
                                              R_C OUT  SYS_REFCURSOR)
    IS 
    BEGIN
      Open R_C for 'select * from ot.employee where deptno in ('
                   || case when data1 = 10 then '10' 
                           Else '10,20' end
                   || ')';
    
    END;
    /
    

    你可以这样调用这个过程:

    Declare
    Rc sys_refcursor;
    Begin
    Ot.check_data(10, rc);
    -- do something with returned cursor
    End;
    /
    

    您可以在 pl/sql 块中打印或使用游标数据:see this qna

    干杯!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-11
      • 1970-01-01
      • 1970-01-01
      • 2018-09-27
      • 1970-01-01
      • 2019-10-27
      • 2020-03-19
      相关资源
      最近更新 更多