参照カーソルからテーブル変数(または配列)にデータを読み込もうとしています。テーブル変数が既存のテーブル%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
は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;
更新:アプリケーションのパフォーマンスを向上させるためにすべてのデータをフェッチする場合は、BULKCOLLECTステートメントを使用する必要があります。
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
ステートメントに一度に1行ずつ必要がない場合は、カーソル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;