【问题标题】:How to fetch Oracle reference cursor into table variable?如何将 Oracle 引用游标提取到表变量中?
【发布时间】:2013-12-23 06:50:54
【问题描述】:

我正在尝试将数据从引用游标加载到表变量(或数组)中,如果表变量基于现有表 %Rowtype 但我的引用游标获取 通过加入多个表加载所以让我尝试演示一个示例我正在尝试做什么,有人可以帮助我

--created table
create table SAM_TEMP(
    col1 number null,
    col2 varchar(100) null
);

--created procedure which outputs results from that table

CREATE OR REPLACE
PROCEDURE SP_OUT_RefCur_PARAM(
    C_RESULT OUT SYS_REFCURSOR
) IS
BEGIN
    OPEN C_RESULT FOR 
        SELECT COL1,COL2
        FROM SAM_TEMP;
END SP_OUT_RefCur_PARAM;

--seeing the output works like this
DECLARE 
    REFCUR SYS_REFCURSOR;   
    outtable SAM_TEMP%rowtype ;  
BEGIN 
    SP_OUT_RefCur_PARAM(REFCUR);
    LOOP
        FETCH REFCUR INTO outtable;
        EXIT WHEN REFCUR%NOTFOUND;
        dbms_output.put_line(outtable.col1);
    END LOOP;
    CLOSE REFCUR;
END;


--but when i try to run below script it is giving error,i think i am missing something
DECLARE 
    REFCUR SYS_REFCURSOR;   
    TYPE REFTABLETYPE IS RECORD (COL1 NUMBER, COL2  VARCHAR(100));
    TYPE TABLETYPE IS TABLE OF REFTABLETYPE;
    outtable TABLETYPE; 
BEGIN 
    SP_OUT_RefCur_PARAM(REFCUR);
    LOOP
        FETCH REFCUR INTO outtable;
        EXIT WHEN REFCUR%NOTFOUND;
        dbms_output.put_line(outtable.col1);
    END LOOP;
    CLOSE REFCUR;
END;

错误报告:

ORA-06550 line 9, column 21:
PLS-00597 expression 'OUTTABLE' in the INTO list is of wrong type
ORA-06550 line 9, column 3:
PL/SQL SQL Statement ignored
ORA-06550 line 11, column 32:
PLS-00302 component 'COL1' must be declared

不知道我错过了什么,在此先感谢您的帮助

【问题讨论】:

  • 刚刚看到输入我的答案。实际上句子应该是“你的变量 outtable 实际上是表类型。”

标签: oracle stored-procedures ref-cursor


【解决方案1】:

上面代码中的变量名误导了你。您的变量 outtable 属于 table 类型。无法将记录数据提取到记录表中,但您可以将其提取到记录本身。

DECLARE 
    REFCUR SYS_REFCURSOR;   
    TYPE RECORDTYPE IS RECORD (COL1 NUMBER, COL2  VARCHAR(100));
    outtable RECORDTYPE; 
BEGIN 
    SP_OUT_RefCur_PARAM(REFCUR);
    LOOP
        FETCH REFCUR INTO outtable;
        EXIT WHEN REFCUR%NOTFOUND;
        dbms_output.put_line(outtable.col1);
    END LOOP;
    CLOSE REFCUR;
END;

更新:如果您想获取所有数据以获得更好的应用程序性能,您需要使用 BULK COLLECT 语句:

DECLARE 
    REFCUR SYS_REFCURSOR;   
    TYPE RECORDTYPE IS
        RECORD (COL1 NUMBER, COL2  VARCHAR(100));
    TYPE TABLETYPE IS
        TABLE OF REFTABLETYPE
        INDEX BY PLS_INTEGER;
    outtable TABLETYPE; 
BEGIN 
    SP_OUT_RefCur_PARAM(REFCUR);
    LOOP
        FETCH REFCUR INTO BULK COLLECT outtable;
        EXIT WHEN outtable.COUNT = 0;

        FOR indx IN 1 .. outtable.COUNT 
        LOOP
            dbms_output.put_line(outtable(indx).col1);;
        END LOOP;
    END LOOP;
    CLOSE REFCUR;
END;

注意:使用 BULK 语句的内存消耗比不使用时要多得多。

了解并开始学习时要记住的最重要的事情 利用 BULK COLLECT 等功能是没有 免费午餐。几乎总是需要在某个地方进行权衡。 与 BULK COLLECT 的权衡,就像许多其他的一样 性能增强功能,是“运行更快但消耗更多 内存。” (Oracle Magazine)

但是,如果您只是获取和处理行 - 在 BULK 语句中不需要每次一行,只需使用游标 FOR LOOP。 (Ask Tom)

【讨论】:

  • 感谢 alexander,这很有效,所以如果我们逐条插入记录,我们需要插入记录本身,如果我们是批量插入(批量收集),那么我们需要创建一个表变量而不是表类型变量对吗?
  • @sam 据我了解,如果您想使用BULK COLLECT,您可以只使用记录集合。我刚刚更新了我的答案,所以你现在可以找到更多信息。
【解决方案2】:

另一种方法是:

DECLARE 
    REFCUR SYS_REFCURSOR;   
    TYPE REFTABLETYPE IS RECORD (COL1 NUMBER, COL2  VARCHAR(100));
    TYPE TABLETYPE IS TABLE OF REFTABLETYPE;
    outtable TABLETYPE; 
BEGIN 
    SP_OUT_RefCur_PARAM(REFCUR);
    FETCH REFCUR BULK COLLECT INTO outtable; 
    FOR i in outtable.First..outtable.Last Loop
        dbms_output.put_line(outtable(i).col1);
    END LOOP;
    CLOSE REFCUR;
END;

【讨论】:

  • 谢谢 wernfried 这是我正在做的,想看看另一个(直接循环光标)是否更快,我搞混了
  • BULK COLLECT 默认应该更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-05
  • 1970-01-01
相关资源
最近更新 更多