Оператор FORALL ожидает оператор SQL - INSERT, UPDATE или DELETE. EXECUTE IMMEDIATE - это оператор PL / SQL, поэтому ваш код создает это исключение.
Вытягивание такого рода трюков не является хорошей идеей в Production. Таблицы должны быть построены с использованием сценариев DDL, а не динамического SQL.
В любом случае, если вы хотите сделать что-то в этом динамическом стиле, вот как это сделать:
Шаг 1: создайте тип SQL, который можно использовать в инструкциях SQL
SQL> create or replace type my_nums as table of number
2 /
Type created.
SQL>
Шаг 2: моя версия вашей процедуры, которая использует тип таблицы SQL вместо PL / SQL. Я переписал предложение FORALL как динамический оператор INSERT, который использует коллекцию в предложении TABLE ().
SQL> declare
2
3 num_tbl my_nums;
4 TYPE ref_cur IS REF CURSOR;
5 cur_emp ref_cur;
6 begin
7 execute immediate 'create table dynamic (v_num number)';
8
9 FOR i in 1..10000 LOOP
10 execute immediate 'insert into dynamic values('||i||')'
11 END LOOP;
12 OPEN cur_emp FOR 'select * from dynamic';
13 FETCH cur_emp bulk collect into num_tbl;
14 close cur_emp;
15
16 execute immediate
17 'insert into dynamic select * from table(:1)' using num_tbl;
18 end;
19 /
PL/SQL procedure successfully completed.
SQL>
Шаг 3: работает
SQL> select count(*) from dynamic
2 /
COUNT(*)
----------
20000
SQL>