ORA-14551: невозможно выполнить операцию DML внутри запроса - PullRequest
3 голосов
/ 19 июля 2010

У меня есть следующее внутри package, и оно выдает мне ошибку:

ORA-14551: cannot perform a DML operation inside a query

Код:

DECLARE 
    CURSOR F IS
        SELECT ROLE_ID 
        FROM ROLE 
        WHERE GROUP = 3 
        ORDER BY GROUP ASC;

BEGIN
FOR R IN F LOOP

DELETE FROM my_gtt_1;
COMMIT;

 INSERT INTO my_gtt_1
  ( USER, role, code, status )
(SELECT 
 trim(r.user), r.role, r.code, MAX(status_id)
FROM 
  table1 r, 
  tabl2 c
WHERE 
      r.role = R.role
  AND r.code IS NOT NULL
  AND c.group = 3
  GROUP BY 
  r.user, r.role, r.code);

  SELECT c.role,
                  c.subgroup,
                  c.subgroup_desc,
                  v_meb_cnt
                  INTO record_type
           FROM   ROLE c
           WHERE c.group = '3' and R.role = '19'
           GROUP BY c.role,c.subgroup,c.subgroup_desc;

  PIPE ROW (record_type);



END LOOP;

END;

Я называю посылку вот так в одной из моих процедур ...:

OPEN cv_1 for SELECT * FROM TABLE(my_package.my_func);

как мне избежать этой ORA-14551 ошибки?

К вашему сведению, я не вставил весь код в цикл. По сути, внутри цикла я ввожу материал в GTT, удаляю материал из GTT, затем выбираю материал из GTT и добавляю его в курсор.

Ответы [ 2 ]

10 голосов
/ 19 июля 2010

Смысл ошибки совершенно ясен: если мы вызываем функцию из оператора SELECT, она не может выполнять операторы DML, то есть операторы INSERT, UPDATE или DELETE или действительно DDL.

Теперь фрагмент кода, который вы опубликовали, содержит вызов PIPE ROW, поэтому вы явно называете его SELECT * FROM TABLE (). Но он включает операторы DELETE и INSERT, поэтому он явно не соответствует уровням чистоты, необходимым для функций в инструкциях SELECT.

Итак, вам нужно удалить эти операторы DML. Вы используете их для заполнения глобальной временной таблицы, но это хорошая новость. Вы не включили никакого кода, который на самом деле использует GTT, поэтому трудно быть уверенным, но использование GTT часто не нужно. Более подробно мы можем предложить обходные пути.

Это связано с другим вашим вопросом ? Если да, то следовали ли вы моему совету, чтобы проверить тот ответ, который я дал на аналогичный вопрос ?


Ради полноты можно включить операторы DML и DDL в функцию, вызываемую в операторе SELECT. Обходной путь должен использовать прагму AUTONOMOUS_TRANSACTION. Это редко хорошая идея, и, конечно, не поможет в этом сценарии. Поскольку транзакция является автономной, сделанные ею изменения невидимы для вызывающей транзакции. В данном случае это означает, что функция не может видеть результат удаления или вставки в GTT.

0 голосов
/ 19 июля 2010

Ошибка означает, что вы ВЫБИРАЕТЕ из функции, которая изменяет данные (УДАЛИТЬ, ВСТАВИТЬ в вашем случае).

Удалите операторы модификации данных из этой функции в отдельный SP, если вам нужна эта функциональность. (Я думаю, из фрагмента кода я не понимаю, почему вы хотите удалить и вставить внутри цикла)

...