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 (Все метки)
Всем привет. Столкнулся с ошибкой Есть функция которая инкрементирует данные в COLUMN1
Я вызываю ее в селекте и получаю ошибку
Код 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 |
|
Куда бежать, на что обратить внимание Чего же здесь непонятного? SELECT — это получение данных, а не их изменение. Вызывай функцию в PL/SQL блоке.
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 |
|
который будет инкрементироваться когда пользователь делает селект Зачем, если не секрет?
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 |
|
получать статистику Штатное средство для этого — включение аудита в БД. Можно также посмотреть в сторону 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:, она была..
![]()
![]()
