ORACLE EXECUTE IMMEDIATE FOR LOOP ORA-06512

Я пытаюсь ВЫПОЛНИТЬ НЕМЕДЛЕННО весь цикл FOR LOOP, но он не работает. Это возможно?

BEGIN
     FOR V_ROW IN (SELECT ROWNUM AS RN,ID AS ID FROM (SELECT ID FROM T_OPDM_PLANDEACCION WHERE IDOPORTUNIDAD=2 ORDER BY ORDEN)) LOOP UPDATE T_OPDM_PLANDEACCION SET ORDEN=V_ROW.RN WHERE ID=V_ROW.ID;END LOOP;
     EXECUTE IMMEDIATE 'FOR V_ROW IN (SELECT ROWNUM AS RN,ID AS ID FROM (SELECT ID FROM T_OPDM_PLANDEACCION WHERE IDOPORTUNIDAD=2 ORDER BY ORDEN)) LOOP UPDATE T_OPDM_PLANDEACCION SET ORDEN=V_ROW.RN WHERE ID=V_ROW.ID;END LOOP';
END;
/

Вторая строка работает очень хорошо, но третья строка (EXECUTE IMMEDIATE 'FOR V_ROW ...') не работает. Строка внутри EXECUTE IMMEDIATE точно такая же, как во второй строке.

Мне нужно выполнить цикл FOR для параметрического выбора.


person dcueva    schedule 05.02.2020    source источник
comment
Если вы хотите, чтобы люди рассмотрели ваш вопрос, постарайтесь сделать код более читабельным. Людям трудно разобрать одну длинную строку всего заглавными буквами. Смешанный регистр делает английский более читабельным. Отступы делают код более читабельным, хотя бы потому, что устраняют необходимость прокрутки.   -  person APC    schedule 05.02.2020
comment
да. Пример не обязательно должен быть динамичным. Строка была построена с использованием имен переменных.   -  person dcueva    schedule 05.02.2020


Ответы (1)


Цикл for - это PL / SQL. Динамического SQL нет. Если вы хотите запускать код PL / SQL динамически, вам необходимо разместить его в блоке PL / SQL внутри динамического оператора:

BEGIN
    EXECUTE IMMEDIATE 'BEGIN FOR V_ROW IN (SELECT ROWNUM AS RN,ID AS ID FROM (SELECT ID FROM T_OPDM_PLANDEACCION WHERE IDOPORTUNIDAD=2 ORDER BY ORDEN)) LOOP UPDATE T_OPDM_PLANDEACCION SET ORDEN=V_ROW.RN WHERE ID=V_ROW.ID;END LOOP;END;';
END;

То есть с добавлением BEGIN и END; (и отсутствующей точкой с запятой) вокруг того, что у вас было.

Как намекнул @APC, вы можете разбить свой оператор на несколько строк, чтобы улучшить читаемость, например:

BEGIN
    EXECUTE IMMEDIATE '
        BEGIN
            FOR V_ROW IN (
                SELECT ROWNUM AS RN,ID AS ID
                FROM (
                    SELECT ID
                    FROM T_OPDM_PLANDEACCION
                    WHERE IDOPORTUNIDAD=2
                    ORDER BY ORDEN
                )
            )
            LOOP
                UPDATE T_OPDM_PLANDEACCION
                SET ORDEN=V_ROW.RN
                WHERE ID=V_ROW.ID;
            END LOOP;
        END;
    ';
END;

Не очевидно, зачем вам это нужно в этом примере. Если вы собираетесь использовать «параметрический выбор», возможно, вы планируете ввести его в динамический оператор; но даже в этом может быть нет необходимости, в зависимости от того, что именно вы имеете в виду и как вы получаете запрос. Непонятно даже, зачем вы вообще это делаете в цикле или с PL / SQL.

person Alex Poole    schedule 05.02.2020
comment
В этом примере я пытаюсь установить последовательный ПОРЯДОК для определения строк внутри определенной ТАБЛИЦЫ с использованием определенного идентификатора для этой таблицы. - person dcueva; 05.02.2020