Меню

Cannot perform a dml operation inside a query ошибка

I have the following inside a package and it is giving me an error:

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

Code is:

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;

I call the package like this in one of my procedures…:

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

how can I avoid this ORA-14551 error?

FYI I have not pasted the entire code inside the loop. Basically inside the loop I am entering stuff in GTT, deleting stuff from GTT and then selecting stuff from GTT and appending it to a cursor.

I am using a Data Analysis tool and the requirement I have was to accept a value from the user, pass that as a parameter and store it in a table. Pretty straighforward so I sat to write this

create or replace
procedure complex(datainput in VARCHAR2)
is
begin
insert into dumtab values (datainput);
end complex;

I executed this in SQL Developer using the following statement

begin
complex('SomeValue');  
end;

It worked fine, and the value was inserted into the table. However, the above statements are not supported in the Data Analysis tool, so I resorted to use a function instead. The following is the code of the function, it compiles.

create or replace
function supercomplex(datainput in VARCHAR2)
return varchar2
is
begin
insert into dumtab values (datainput);
return 'done';
end supercomplex;   

Once again I tried executing it in SQL Developer, but I got cannot perform a DML operation inside a query upon executing the following code

select supercomplex('somevalue') from dual;

My question is
— I need a statement that can run the mentioned function in SQL Developer or
— A function that can perform what I am looking for which can be executed by the select statement.
— If it is not possible to do what I’m asking, I would like a reason so I can inform my manager as I am very new (like a week old?) to PL/SQL so I am not aware of the rules and syntaxes.

P.S. How I wish this was C++ or even Java 🙁

EDIT

I need to run the function on SQL Developer because before running it in DMine (which is the tool) in order to test if it is valid or not. Anything invalid in SQL is also invalid in DMine, but not the other way around.

Thanks for the help, I understood the situation and as to why it is illegal/not recommended

i_am_kisly

4 / 4 / 0

Регистрация: 26.08.2014

Сообщений: 110

1

09.06.2017, 11:43. Показов 13245. Ответов 5

Метки oracle 11g (Все метки)


Всем привет. Столкнулся с ошибкой
ORA-14551: невозможно выполнение операции DML внутри запроса
У меня есть таблица TABLE1 c COLUMN1. В COLUMN1 записано некоторое число.

Есть функция которая инкрементирует данные в COLUMN1

SQL
1
2
3
4
5
6
CREATE OR REPLACE FUNCTION FUNCTION1 RETURN NUMBER AS 
BEGIN
    UPDATE TABLE1 SET COLUMN1 = COLUMN1 + 1;
    COMMIT;
    RETURN NULL;
END FUNCTION1;

Я вызываю ее в селекте и получаю ошибку

SQL
1
SELECT FUNCTION1() FROM DUAL

Код

ORA-14551: невозможно выполнение операции DML внутри запроса 
ORA-06512: на  "FUNCTION1", line 3
14551. 00000 -  "cannot perform a DML operation inside a query "
*Cause:    DML operation like insert, update, delete or select-for-update
           cannot be performed inside a query or under a PDML slave.
*Action:   Ensure that the offending DML operation is not performed or
           use an autonomous transaction to perform the DML operation within
           the query or PDML slave.

Раньше не сталкивался. Куда бежать, на что обратить внимание ?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Модератор

4186 / 3026 / 576

Регистрация: 21.01.2011

Сообщений: 13,096

09.06.2017, 12:10

2

Цитата
Сообщение от i_am_kisly

Куда бежать, на что обратить внимание

Чего же здесь непонятного? SELECT — это получение данных, а не их изменение. Вызывай функцию в PL/SQL блоке.
В сообщении еще сказано, что можно использовать автономную транзакцию, но с этим средством надо обращаться осторожно, поэтому в данном случае я бы не советовал.
Кстати, в оф. доке перечислены ограничения на функции, которые предполагается вызывать в SELECT.



0



4 / 4 / 0

Регистрация: 26.08.2014

Сообщений: 110

09.06.2017, 12:21

 [ТС]

3

Я хочу сделать что-то вроде «select trigger», чтобы иметь счетчик который будет инкрементироваться когда пользователь делает селект.



0



Модератор

4186 / 3026 / 576

Регистрация: 21.01.2011

Сообщений: 13,096

09.06.2017, 12:35

4

Цитата
Сообщение от i_am_kisly
Посмотреть сообщение

который будет инкрементироваться когда пользователь делает селект

Зачем, если не секрет?



0



4 / 4 / 0

Регистрация: 26.08.2014

Сообщений: 110

09.06.2017, 13:07

 [ТС]

5

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



0



Модератор

4186 / 3026 / 576

Регистрация: 21.01.2011

Сообщений: 13,096

09.06.2017, 13:42

6

Цитата
Сообщение от i_am_kisly
Посмотреть сообщение

получать статистику

Штатное средство для этого — включение аудита в БД. Можно также посмотреть в сторону RLS (Row Level Security) — пакет dbms_rls



0



May 10, 2021

I got ” ORA-14551: cannot perform a DML operation inside a query ”  error in Oracle database.

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

Details of error are as follows.

ORA-14551 cannot perform a DML operation inside a query

Cause: DML operation like insert, update, delete or select-for-update cannot be performed 
inside a query or under a PDML slave.

Action: Ensure that the offending DML operation is not performed or use an autonomous
 transaction to perform the DML operation within the query or PDML slave.

cannot perform a DML operation inside a query

This ORA-14551 error is related with the DML operation like insert, update, delete or select-for-update cannot be performed inside a query or under a PDML slave.

Ensure that the offending DML operation is not performed or use an autonomous transaction to perform the DML operation within the query or PDML slave.

You should use the PRAGMA AUTONOMOUS_TRANSACTION;

You should give commit explicitly inside the function;

OR if you got this error when you run function as follows.

SQL> select testfunction('test') from dual;

Then run it as follows.

SQL> var myvar NUMBER;
SQL> call testfunction('test') into :myvar;  

Call completed.

Do you want to learn Oracle Database for Beginners, then read the following articles.

Oracle Tutorial | Oracle Database Tutorials for Beginners ( Junior Oracle DBA )

 1,488 views last month,  1 views today

About Mehmet Salih Deveci

I am Founder of SysDBASoft IT and IT Tutorial and Certified Expert about Oracle & SQL Server database, Goldengate, Exadata Machine, Oracle Database Appliance administrator with 10+years experience.I have OCA, OCP, OCE RAC Expert Certificates I have worked 100+ Banking, Insurance, Finance, Telco and etc. clients as a Consultant, Insource or Outsource.I have done 200+ Operations in this clients such as Exadata Installation & PoC & Migration & Upgrade, Oracle & SQL Server Database Upgrade, Oracle RAC Installation, SQL Server AlwaysOn Installation, Database Migration, Disaster Recovery, Backup Restore, Performance Tuning, Periodic Healthchecks.I have done 2000+ Table replication with Goldengate or SQL Server Replication tool for DWH Databases in many clients.If you need Oracle DBA, SQL Server DBA, APPS DBA,  Exadata, Goldengate, EBS Consultancy and Training you can send my email adress [email protected].-                                                                                                                                                                                                                                                 -Oracle DBA, SQL Server DBA, APPS DBA,  Exadata, Goldengate, EBS ve linux Danışmanlık ve Eğitim için  [email protected] a mail atabilirsiniz.

 Scenario:

SQL> DROP TABLE t PURGE;
Table T dropped.

SQL> CREATE TABLE t (
  2      c1 INT GENERATED AS IDENTITY
  3  );
Table T created.

SQL> INSERT INTO t VALUES ( DEFAULT );
1 row inserted.

SQL> INSERT INTO t VALUES ( DEFAULT );
1 row inserted.

SQL> COMMIT;
Commit complete.

SQL> SELECT * FROM t;
   C1
_____
    1
    2

SQL> CREATE OR REPLACE FUNCTION f RETURN INT AS
  2      retval INT;
  3  BEGIN
  4      INSERT INTO t VALUES ( DEFAULT ) RETURNING c1 INTO retval;
  5      RETURN retval;
  6  END f;
  7  /
Function F compiled

SQL> SELECT f FROM t;
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "DONGHUA.F", line 4

SQL> WITH x AS (
  2      SELECT /*+ materialize */ f FROM t
  3  )
  4  SELECT *
  5  FROM x;
   F
____
   4
   3

Testing script:

DROP TABLE t PURGE;

CREATE TABLE t (
    c1 INT GENERATED AS IDENTITY
);

INSERT INTO t VALUES ( DEFAULT );
INSERT INTO t VALUES ( DEFAULT );
COMMIT;

SELECT * FROM t;


CREATE OR REPLACE FUNCTION f RETURN INT AS
    retval INT;
BEGIN
    INSERT INTO t VALUES ( DEFAULT ) RETURNING c1 INTO retval;
    RETURN retval;
END f;
/

SELECT f FROM t;

WITH x AS (
    SELECT /*+ materialize */ f FROM t
)
SELECT *
FROM x;

У меня внутри 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 ответа

Лучший ответ

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

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

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

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


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


11

Community
23 Май 2017 в 15:31

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

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


0

devio
19 Июл 2010 в 15:59

 
O’ShinW ©
 
(2013-03-29 12:09)
[0]

С тем, что бы использовать
 Insert into SomeTable (Id, ….. )  values ( GetNewId(«SomeText»), ….. )

где
create or replace function GetNewId(p_NAME in varchar) return number is
 Result number;
begin
 select SEQ_ND_ID.NextVal into Result from dual;

 insert into Tab_FOO(ID, NAME) values (Result, p_NAME);
— Естественно, ORA-14551: cannot perform a DML operation inside a query

 return(Result);
end GetNewId;

Читаю совет
   Myfunction looks like this

   create or replace function myFunction return varchar2 as
   begin
   update emp set empno = empno +1 where empno = 0;
   return «Yeah»;
   end;
   /

   SQL> insert into emp (empno, ename) values (0, «TEST»);
   1 row created.
   SQL> var myVar VARCHAR2
   SQL> SELECT myFunction INTO :myVar FROM DUAL;
   SELECT myFunction INTO :myVar FROM DUAL
   *
   ERROR at line 1:
   ORA-14551: cannot perform a DML operation inside a query
   ORA-06512: at «SCOTT.MYFUNCTION», line 3
   ORA-06512: at line 1
The solution concerns using different syntax, such as below:
   You need to use the syntax:
   SQL> var myVar VARCHAR2
   SQL> call myFunction() INTO :myVar;
   Call completed.

но я хочу именно
>> DML operation inside a query
например, insert into … select GetNewId(«SomeText»), остальные поля

Можно «вывернуться»?

Аудит не предлагайте, это не то.
Требование — заносить сквозные ID в таблицу, с комментариями. Причем, эта таблица первична. Нельзя никуда вставить новый ID? предварительно не занеся в нее.. FK-PK, короче


 
O’ShinW ©
 
(2013-03-29 12:11)
[1]


> Нельзя никуда вставить новый ID?

? = ,

Подозреваю, что ерунду хотят.
Но такое требование, не знаю зачем это надо


 
Игорь Шевченко ©
 
(2013-03-29 12:52)
[2]


>  Insert into SomeTable (Id, ….. )  values ( GetNewId(«SomeText»),
>  ….. )

values (select GetNewId(«SomeText») from dual,


 
Медвежонок Пятачок ©
 
(2013-03-29 13:18)
[3]

прагма афтономус транзакшон

внутри функции


 
O’ShinW ©
 
(2013-03-29 14:55)
[4]


> прагма афтономус транзакшон

так заработало.
+ ниже


> values (select GetNewId(«SomeText») from dual,

Раньше не работало, было так: Вариант1
create or replace function MF_ARGUS.NewND(p_NAME in varchar) return number  is
 Result number;
begin
 select MF_ARGUS.SEQ_ND_ID.NextVal into Result from dual;
 insert into MF_ARGUS.tabfoo values (result, p_NAME);
 return(Result);
end NewND;

преписал как: Вариант2
create or replace function MF_ARGUS.NewND(p_NAME in varchar) return number
 as PRAGMA AUTONOMOUS_TRANSACTION; Result number;
begin
 select MF_ARGUS.SEQ_ND_ID.NextVal into Result from dual;
 insert into MF_ARGUS.tabfoo values (result, p_NAME);
 commit;
 return(Result);
end NewND;

как сказал выше, Вариант 2 заработал..
НО,
вернул назад(случайно, так получилось, не в том окне нажал)

Сейчас откатилось к варианту1, еще раз привожу
create or replace function MF_ARGUS.NewND(p_NAME in varchar) return number
 is Result number;
begin
 select MF_ARGUS.SEQ_ND_ID.NextVal into Result from dual;
 insert into MF_ARGUS.tabfoo values (result, p_NAME);
 return(Result);
end NewND;

Пробую
insert into mf_argus.tabfoo2 (FOO, NAME)
values (MF_ARGUS.NewND(«test»), «test2»);
Все ok..

insert into mf_argus.tabfoo2 F (FOO, NAME)
select MF_ARGUS.NewND(«test2»), T.NAME from applic.T_TOWN T;
Все ok..

А раньше не работало. Я ж не придумал ошибку ORA-14551:, она была..


0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Cannot launch battle net ошибка
  • Cannot instantiate the type ошибка