Решение "не может выполнить операцию DML внутри запроса"? - PullRequest
25 голосов
/ 04 января 2012

Я использую инструмент анализа данных, и у меня было требование принять значение от пользователя, передать его в качестве параметра и сохранить его в таблице. Довольно просто, поэтому я сел написать это

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

Я выполнил это в SQL Developer , используя следующую инструкцию

begin
complex('SomeValue');  
end;

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

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. Как бы я хотел, чтобы это был C ++ или даже Java: (

EDIT

Мне нужно запустить функцию в SQL Developer, потому что перед запуском ее в DMine (которая является инструментом), чтобы проверить, является ли она действительной или нет. Все недопустимое в SQL также недопустимо в DMine, но не наоборот.

Спасибо за помощь, я понял ситуацию и почему нелегально / не рекомендуется

Ответы [ 2 ]

42 голосов
/ 04 января 2012

Вы можете использовать директиву 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

Том Кайт имеет хорошее объяснение о том, почему ошибка возникает в первую очередь. Это небезопасно, потому что это может зависеть от порядка, в котором обрабатываются строки. Более того, Oracle не гарантирует, что функция будет выполняться по крайней мере один раз и максимум один раз в строке.

12 голосов
/ 04 января 2012

Просто объявите переменную для принятия возвращаемого значения, например:

declare
    retvar varchar2(4);
begin
    retvar := supercomplex('somevalue');
end;

Выбор не работает, потому что функция выполняет вставку, если все, что она сделала, вернула значение, то это сработало бы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...