BULK COLLECT INTOを使うとSELECTやフェッチで一度に複数のレコードを取得することができる。
バルクフェッチでの使用例
SET SERVEROUTPUT ON; DECLARE --*=====================================================* --* 変数定義 * --*=====================================================* --カーソル定義 CURSOR CURTMP_TBL_A IS SELECT USERID ,MONEY FROM TMP_TBL_A ; --テーブル型を定義 TYPE CURTMP_TBL_A_TBL_TYPE IS TABLE OF CURTMP_TBL_A%ROWTYPE INDEX BY BINARY_INTEGER; --テーブル型変数を定義 WK_TMP_TBL_A CURTMP_TBL_A_TBL_TYPE; BEGIN --開始時間の出力 DBMS_OUTPUT.PUT_LINE('START = ' || TO_CHAR(SYSTIMESTAMP,'YYYYMMDDHH24MISSFF3')); OPEN CURTMP_TBL_A; --カーソルのループ LOOP --バルクフェッチ (LIMITは1回での取得件数を指定するオプション) FETCH CURTMP_TBL_A BULK COLLECT INTO WK_TMP_TBL_A LIMIT 10000; --テーブル型変数の終端までループ FOR I IN WK_TMP_TBL_A.FIRST..WK_TMP_TBL_A.LAST LOOP WK_TMP_TBL_A( I ).MONEY := MONEY * 10; --変数の値をINSERT INSERT INTO TMP_TBL_B ( USERID ,MONEY )VALUES( WK_TMP_TBL_A( I ).USERID ,WK_TMP_TBL_A( I ).MONEY ); END LOOP; --カーソルのEOF判定 IF CURTMP_TBL_A%NOTFOUND THEN EXIT; END IF; END LOOP; --カーソルのクローズ CLOSE CURTMP_TBL_A; --終了時間の出力 DBMS_OUTPUT.PUT_LINE('END = ' || TO_CHAR(SYSTIMESTAMP,'YYYYMMDDHH24MISSFF3')); END; /
あまりにもたくさんのレコード(メモリより大きい)を取得しようとすると逆にパフォーマンスが低下する恐れがある。
それを防止するためLIMIT句で一度に取得するデータの行数を指定することも可能。
SELECTでの使用例
DECLARE --テーブル型を定義 TYPE TMP_TBL_A_TYPE IS TABLE OF TMP_TBL_A%ROWTYPE INDEX BY BINARY_INTEGER; --テーブル型変数を定義 WK_TMP_TBL_A WK_TMP_TBL_A_TYPE; BEGIN SELECT * BULK COLLECT INTO WK_TMP_TBL_A FROM TMP_TBL_A ; END; /
パフォーマンスを向上させる手段のうちの1つだが、
カーソルでLIMIT句を使用する場合はループが2重になるのでプログラムが複雑になってしまう。
なので、あまり複雑なプログラムで使用するのは不向き。
また、使用例のような簡単なプログラム(SELECTの結果を少し加工してINSERTとか)であれば
カーソルを使用せずSELECT & INSERT 等を使用した方が速い & 判りやすい。
上記のことを踏まえ、使用の際は要検討のこと。