2010-05-19 19 views
13

Estoy trabajando en una consulta (un SELECTO) y necesito insertar el resultado de este en una tabla. Antes de hacer la inserción, tengo algunas verificaciones que hacer, y si todas las columnas son válidas, haré la inserción.procedimiento almacenado llamada oráculo dentro de seleccione

La comprobación se realiza en un procedimiento almacenado. El mismo procedimiento se usa en otro lugar también. Así que estoy pensando en usar el mismo procedimiento para hacer mis comprobaciones.

El procedimiento hace las comprobaciones e inserta los valores, todo está bien.

Intenté llamar al procedimiento dentro de mi SELECT pero no funciona.

SELECT field1, field2, myproc(field1, field2) 

from MYTABLE. 

Este tipo de código no funciona.

Creo que se puede hacer usando un cursor, pero me gustaría evitar los cursores. Estoy buscando la solución más fácil.

¿Alguien, alguna idea?

Respuesta

25

utilizar un bucle PL/SQL:

BEGIN 
    FOR c IN (SELECT field1, field2 FROM mytable) LOOP 
     my_proc(c.field1, c.field2); 
    END LOOP; 
END; 
+0

Es lo que necesito. Gracias. –

0

No puede usar procedimientos almacenados en la instrucción SELECT. Puede usar funciones para eso.

Como tengo entendido, está llamando a insertar en su SP, así que tenga en cuenta que puede utilizar INSERT/UPDATE en el cuerpo de la función. Pero si necesita hacer algunos controles, puede usar la función que lo hará y usar esa función en su declaración seleccionada.

+0

Sí, esta sería la solución definitiva, pero me gustaría utilizar el SP existente porque es parte de un proyecto grande, y no quiero hacer nuevas funciones. Sería más difícil de mantener. –

6

SQL sólo puede utilizar las funciones de la proyección: se necesita algo que devuelve un valor. Entonces vas a tener que escribir algunas funciones. Esa es la mala noticia. La buena noticia es que puede reutilizar toda la inversión en sus procedimientos almacenados.

Aquí hay un procedimiento que impone una regla comercial completamente equitativa: solo los gerentes pueden tener un salario alto.

SQL> create or replace procedure salary_rule 
    2  (p_sal in emp.sal%type 
    3  , p_job in emp.job%type) 
    4 is 
    5  x_sal exception; 
    6 begin 
    7  if p_sal > 4999 and p_job != 'MANAGER' then 
    8   raise x_sal; 
    9  end if; 
10 exception 
11  when x_sal then 
12   raise_application_error(-20000, 'Only managers can earn that much!'); 
13 end salary_rule; 
14/

Procedure created. 

SQL> 

Como es un procedimiento, no podemos usarlo en una instrucción SELECT; tenemos que envolverlo en una función. Esta función solo llama al procedimiento almacenado. Devuelve el parámetro de entrada P_SAL. En otras palabras, si el salario es válido (de acuerdo con las reglas) será devuelto. De lo contrario, la función volverá a lanzar la excepción del procedimiento almacenado.

SQL> create or replace function validate_salary 
    2  (p_sal in emp.sal%type 
    3  , p_job in emp.job%type) 
    4  return emp.sal%type 
    5 is 
    6 begin 
    7  salary_rule(p_sal, p_job); 
    8  return p_sal; 
    9 end validate_salary; 
10/

Function created. 

SQL> 

La función tiene que devolver un valor que queremos insertar en nuestra tabla. No puede devolver una frase sin sentido como "salario correcto". Además, si queremos validar dos columnas, necesitamos una función separada para cada una, incluso si existe una relación entre ellas y usamos el mismo procedimiento almacenado para validar ambas. Buen uso de la palabra clave DETERMINISTIC.

Aquí está la prueba: fontaneros no pueden ganar 5000 spondulicks ....

SQL> insert into emp 
    2  (empno 
    3  , ename 
    4  , job 
    5  , deptno 
    6  , sal) 
    7 select 
    8  emp_seq.nextval 
    9  , 'HALL' 
10  , 'PLUMBER' 
11  , 60 
12  , validate_salary(5000, 'PLUMBER') 
13 from dual 
14/
    , validate_salary(5000, 'PLUMBER') 
     * 
ERROR at line 12: 
ORA-20000: Only managers can earn that much! 
ORA-06512: at "APC.SALARY_RULE", line 12 
ORA-06512: at "APC.VALIDATE_SALARY", line 7 


SQL> 

... pero los administradores pueden (porque se lo merecen):

SQL> insert into emp 
    2  (empno 
    3  , ename 
    4  , job 
    5  , deptno 
    6  , sal) 
    7 select 
    8  emp_seq.nextval 
    9  , 'HALL' 
10  , 'MANAGER' 
11  , 60 
12  , validate_salary(5000, 'MANAGER') 
13 from dual 
14/

1 row created. 

SQL> 

Tenga en cuenta que la excepción lanzada es crucial para este trabajo.No podemos escribir algo raro SI EL SALARIO ES VÁLIDO Y LUEGO INSERTAR la lógica en nuestra declaración de SQL. Por lo tanto, si el procedimiento almacenado no genera una excepción sino que devuelve un estado de error débil, la función de ajuste tendrá que interpretar la salida y arrojar su propia excepción.

+0

En realidad, mi procedimiento almacenado hace la inserción. Entonces no puedo usar una inserción en seleccionar. –

Cuestiones relacionadas