2012-01-04 390 views
19

Estoy usando una herramienta de análisis de datos y el requisito que tengo es aceptar un valor del usuario, pasarlo como un parámetro y almacenarlo en una tabla. Bastante directo conducir así que me senté a escribir este¿Solución para "no se puede realizar una operación DML dentro de una consulta"?

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

ejecuté esto en SQL Developer mediante la siguiente instrucción

begin 
complex('SomeValue'); 
end; 

Trabajó muy bien, y se insertó el valor en la tabla. Sin embargo, las declaraciones anteriores no son compatibles con la herramienta de análisis de datos, por lo que recurrí al uso de una función. El siguiente es el código de la función, compila.

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

Una vez más trató de ejecutarlo en SQL Developer, pero tengo no puede realizar una operación DML dentro de una consulta al ejecutar el siguiente código

select supercomplex('somevalue') from dual; 

Mi pregunta es - I necesita una declaración que puede ejecutar la función mencionada en SQL Developer o - Una función que puede realizar lo que estoy buscando y que puede ser ejecutado por el declaración. - Si no es posible hacer lo que estoy pidiendo, me gustaría un motivo para informarle a mi gerente, ya que soy muy nuevo (¿como una semana?) De PL/SQL, así que no estoy al tanto de las reglas y sintaxis

P.S. Cómo me gustaría que esto era C++ o incluso Java :(

EDITAR

necesito para ejecutar la función de SQL Developer porque antes de ejecutarlo en DMine (que es la herramienta) con el fin de comprobar si se trata de Cualquier cosa válida o no. válida en SQL también es válida en DMine, pero no al revés.

Gracias por la ayuda, entendía la situación y por qué es ilegal/no recomendado

+0

El error que está recibiendo no es específico de SQL Developer, es un error de Oracle y es bastante sencillo: no puede realizar modificaciones en la base de datos en una consulta. Presumiblemente esto se debe a los niveles de aislamiento, para mantener el cumplimiento de ACID; de lo contrario, ¡podrías modificar las tablas que consultaste al mismo tiempo y todo el Infierno se desataría! – Xophmeister

+0

¿Puede explicar por qué necesita llamar a una función en SQL Developer? ¿Por que importa? – APC

+0

no es compatible con la herramienta de análisis de datos? que herramienta? Si puede ejecutar SQL en esta herramienta, debería poder ejecutar un script (el bloque anónimo que muestra inicialmente). – tbone

Respuesta

33

Puede utilizar la directiva pragma autonomous_transaction. Esto ejecutará la función en una transacción independiente que podrá realizar DML sin aumentar el ORA-14551.

Tenga en cuenta que dado que el autonomous transaction es independiente, los resultados del DML se comprometerán fuera del alcance de la transacción principal. En la mayoría de los casos, esa no sería una solución aceptable.

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 acerca de por qué el error se eleva en el primer lugar. No es seguro porque puede depender del orden en que se procesen las filas. Además, Oracle no garantiza que la función se ejecutará al menos una vez y como máximo una vez por fila.

10

Sólo declarar una variable para aceptar el valor de retorno, por ejemplo:

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

La selección no funciona porque la función está realizando una inserción, si todo lo que hizo fue devolver un valor, entonces funcionaría.

+1

Olvidó incluir la variable para mantener el valor devuelto. – APC

Cuestiones relacionadas