BULK COLLECT


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 等を使用した方が速い & 判りやすい。


上記のことを踏まえ、使用の際は要検討のこと。