Как получить ссылочный курсор Oracle в переменную таблицы?

Я пытаюсь загрузить данные из ссылочного курсора в переменную таблицы( или массив), ссылочный курсор работает, если переменная таблицы основана на existingtable %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

Не уверен, что мне не хватает, заранее спасибо за помощь

2 ответов


имя переменной в коде выше ввело вас в заблуждение. Переменная 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 COLLECT является то, что нет бесплатный обед. Почти всегда где-то можно найти компромисс. Компромисс с BULK COLLECT, как и многие другие улучшающие производительность функции: "работать быстрее, но потреблять больше память."(Журнал Oracle)

но если вы просто извлекаете и обрабатываете строки-строки за раз нет нуждается в BULK оператор, просто используйте курсор FOR LOOP. (Спросить Тома)


другой способ сделать это:

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;