Решение проблемы "не может выполнить операцию DML внутри запроса"?
Я использую инструмент анализа данных, и я должен был принять значение от пользователя, передать это как параметр и сохранить его в таблице. Довольно напряженный, поэтому я сидел, чтобы написать это
create or replace
procedure complex(datainput in VARCHAR2)
is
begin
insert into dumtab values (datainput);
end complex;
Я выполнил это в SQL Developer, используя следующую инструкцию
begin
complex('SomeValue');
end;
Он работал нормально, и значение было вставлено в таблицу. Однако приведенные выше утверждения не поддерживаются в инструменте Data Analysis, поэтому я прибегнул к использованию функции. Ниже приведен код функции, который он компилирует.
create or replace
function supercomplex(datainput in VARCHAR2)
return varchar2
is
begin
insert into dumtab values (datainput);
return 'done';
end supercomplex;
Снова я попытался выполнить его в SQL Developer, но я получил , не выполнив операцию DML внутри запроса после выполнения следующего кода
select supercomplex('somevalue') from dual;
Мой вопрос:
- Мне нужно выражение, которое может запустить указанную функцию в SQL Developer или
- Функция, которая может выполнять то, что я ищу, которое может быть выполнено оператором select.
- Если невозможно сделать то, что я прошу, я бы хотел повести, чтобы я мог сообщить своему менеджеру, как я очень новый (например, неделю назад?) В PL/SQL, поэтому я не знаю правил и синтаксисы.
P.S. Как бы я хотел, чтобы это был С++ или даже Java: (
ИЗМЕНИТЬ
Мне нужно запустить функцию на SQL Developer, потому что перед ее запуском в DMine (который является инструментом), чтобы проверить, действительно ли это или нет. Все, что недействительно в SQL, также неверно в DMine, но не наоборот.
Спасибо за помощь, я понял ситуацию и почему она незаконна/не рекомендуется
Ответы
Ответ 1
Вы можете использовать директиву pragma autonomous_transaction
. Это запустит эту функцию в независимую транзакцию, которая сможет выполнять DML без повышения ORA-14551.
Имейте в виду, что поскольку автономная транзакция независима, результаты DML будут выполняться за пределами области родительской транзакции. В большинстве случаев это не было бы приемлемым решением.
SQL> CREATE OR REPLACE FUNCTION supercomplex(datainput IN VARCHAR2)
2 RETURN VARCHAR2 IS
3 PRAGMA AUTONOMOUS_TRANSACTION;
4 BEGIN
5 INSERT INTO dumtab VALUES (datainput);
6 COMMIT;
7 RETURN 'done';
8 END supercomplex;
9 /
Function created
SQL> SELECT supercomplex('somevalue') FROM dual;
SUPERCOMPLEX('SOMEVALUE')
--------------------------------------------------------------------------------
done
SQL> select * from dumtab;
A
--------------------------------------------------------------------------------
somevalue
Tom Kyte имеет приятное объяснение о том, почему ошибка возникает в первую очередь. Это не безопасно, потому что это может зависеть от порядка обработки строк. Кроме того, Oracle не гарантирует, что функция будет выполняться как минимум один раз и не более одного раза в строке.
Ответ 2
Просто объявите переменную для принятия возвращаемого значения, например:
declare
retvar varchar2(4);
begin
retvar := supercomplex('somevalue');
end;
Выбор не работает, потому что функция выполняет вставку, если все, что она сделала, это вернуть значение, то оно будет работать.