解决方案“无法在查询中执行DML操作”?

时间:2012-01-04 15:20:16

标签: sql oracle function stored-procedures plsql

我正在使用数据分析工具,我的要求是接受用户的值,将其作为参数传递并将其存储在表中。非常直截了当所以我坐下来写这个

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

我使用以下语句

SQL Developer 中执行了此操作
begin
complex('SomeValue');  
end;

它工作正常,并将值插入表中。但是,数据分析工具不支持上述语句,因此我使用了函数。以下是函数的代码,它编译。<​​/ p>

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 :(

修改

我需要在SQL Developer上运行该函数,因为在DMine(这是工具)中运行它之前,为了测试它是否有效。 SQL中的任何无效内容在DMine中也是无效的,但不是相反。

感谢您的帮助,我理解了这种情况以及为什么它是非法的/不推荐的

3 个答案:

答案 0 :(得分:39)

您可以使用指令pragma autonomous_transaction。这将把函数运行到一个独立的事务中,该事务将能够执行DML而不需要提升ORA-14551。

请注意,由于autonomous transaction是独立的,因此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 has a nice explanation首先提出错误的原因。它不安全,因为它可能取决于行的处理顺序。此外,Oracle不保证该函数至少执行一次,每行最多执行一次。

答案 1 :(得分:12)

只需声明一个变量来接受返回值,例如:

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

select不起作用,因为函数正在执行插入操作,如果它只是返回一个值,那么它就可以工作。

答案 2 :(得分:1)

只需在伪if ... end if;语句中执行该函数即可忽略返回值:

exec if supercomplex('somevalue') then null; end if;

或将其作为put_line过程的参数执行以输出返回值:

exec dbms_ouput ('result of supercomplex='||supercomplex('somevalue'));

result of supercomplex=done