FORALL
は、実際にはLOOP
またはイテレータではありませんが、BULK
DML
の操作です。これは、コレクション内のエントリごとに操作を実行しませんが、コレクション内のすべてのエントリに対して1つのDML操作を実行します。 Dynamic SQL
をBULK
に実行することはできず、反復できません。 EXECUTE IMMEDIATE
を繰り返し実行するには、LOOP
を使用する必要があります(または別の方法をとる)。
例を示します。コミットサイズを制御するのにまだBULK COLLECT
が使用されますが、FOR LOOP
にはDynamic SQL
があります。 (注意:動的SQLのこのボリュームを行うことは効率的ではない単なる例あなたの元のコレクションのサイズを維持する。)
は、テストデータの設定:
CREATE TABLE TEST_TABLE (
TEST_ID NUMBER
);
INSERT INTO TEST_TABLE SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= 50001;
初期データ:次に
SELECT * FROM TEST_TABLE ORDER BY 1 DESC FETCH FIRST 5 ROWS ONLY;
TEST_ID
50001
50000
49999
49998
49997
実行をブロック。これはFORALL
BULK DML
を使用しません。これは、代わりに使用していますFOR LOOP
:
DECLARE
CURSOR EX01_CURSOR IS (
SELECT 'UPDATE TEST_TABLE SET TEST_TABLE.TEST_ID = TEST_TABLE.TEST_ID + 100000 WHERE TEST_TABLE.TEST_ID = ' ||
TEST_TABLE.TEST_ID AS UPDATE_QUERY
FROM TEST_TABLE);
TYPE EX01_CUR_TYPE IS TABLE OF EX01_CURSOR%ROWTYPE;
QUERIES EX01_CUR_TYPE;
BEGIN
QUERIES := EX01_CUR_TYPE();
OPEN EX01_CURSOR;
LOOP
FETCH EX01_CURSOR BULK COLLECT INTO QUERIES LIMIT 50000;
EXIT WHEN QUERIES.COUNT = 0;
FOR UPDATE_POINTER IN 1..QUERIES.COUNT
LOOP
EXECUTE IMMEDIATE QUERIES(UPDATE_POINTER).UPDATE_QUERY;
END LOOP;
COMMIT;
END LOOP;
CLOSE EX01_CURSOR;
END;
/
PL/SQL procedure successfully completed.
結果:
SELECT * FROM TEST_TABLE ORDER BY 1 DESC FETCH FIRST 5 ROWS ONLY;
TEST_ID
150001
150000
149999
149998
149997
言語/技術にタグを付けてください。彼らは何を見ているのか分からないと、どうやって助けてくれるのですか?それ以上をSOに転記する前にこれをお読みください:https://stackoverflow.com/help/asking –
参照https://stackoverflow.com/questions/27814535/getting-error-pls-00435-dml-statement-without-バルクインバインド - 使用不可 - 内部 –