8

参照カーソルからテーブル変数 (または配列) にデータをロードしようとしています。テーブル変数が 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

何が欠けているのかわからない、助けてくれてありがとう

4

2 に答える 2

9

上記のコードの変数の名前は誤解を招きました。あなたの変数outtabletable型にあります。レコード データをテーブル オブ レコードにフェッチすることはできませんが、レコード自体にフェッチすることはできます。

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 のトレードオフは、「実行は高速になりますが、より多くのメモリを消費する」ことです。(オラクルマガジン)

ただし、行をフェッチして処理するだけの場合-一度に1行ずつBULKステートメントに必要がない場合は、カーソルを使用してくださいFOR LOOP。(トムに聞く)

于 2013-12-06T04:58:44.793 に答える