2010-05-19 6 views
13

Sto lavorando su una query (un SELECT) e ho bisogno di inserire il risultato di questo in una tabella. Prima di fare l'inserto ho qualche controllo da fare, e se tutte le colonne sono valide, farò l'inserto.procedura memorizzata chiamata oracle all'interno select

Il controllo viene eseguito in una stored procedure. La stessa procedura viene utilizzata anche altrove. Quindi sto pensando di utilizzare la stessa procedura per eseguire i miei controlli.

La procedura esegue i controlli e inserisce i valori è tutto OK.

Ho provato a chiamare la procedura all'interno del mio SELECT ma non funziona.

SELECT field1, field2, myproc(field1, field2) 

from MYTABLE. 

Questo tipo di codice non funziona.

Penso che si possa fare usando un cursore, ma vorrei evitare i cursori. Sto cercando la soluzione più semplice.

Qualcuno, qualche idea?

risposta

25

utilizzare un ciclo di PL/SQL:

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

È quello di cui ho bisogno. Grazie. –

0

Non è possibile utilizzare stored procedure nell'istruzione SELECT. È possibile utilizzare le funzioni per questo.

Come ho capito, stai chiamando insert nel tuo SP, quindi prendi in considerazione che puoi usare INSERT/UPDATE nel corpo della funzione. Ma se è necessario eseguire alcuni controlli, è possibile utilizzare la funzione che eseguirà tali controlli e utilizzerà quella funzione nell'istruzione select.

+0

Sì, questa sarebbe la soluzione definitiva, ma mi piacerebbe utilizzare l'SP esistente perché fa parte di un grande progetto e non voglio fare nuove funzioni. Sarebbe più difficile da mantenere. –

6

SQL può utilizzare solo le funzioni nella proiezione: ha bisogno di qualcosa che restituisce un valore. Quindi dovrai scrivere alcune funzioni. Questa è la brutta notizia. La buona notizia è che puoi riutilizzare tutto l'investimento nelle tue stored procedure.

Ecco una procedura che applica una regola aziendale completamente giusta: solo i dirigenti possono avere uno stipendio 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> 

Poiché si tratta di una procedura che non possiamo utilizzarlo in un'istruzione SELECT; abbiamo bisogno di avvolgerlo in una funzione. Questa funzione chiama solo la stored procedure. Restituisce il parametro di input P_SAL. In altre parole, se lo stipendio è valido (secondo le regole) verrà restituito. In caso contrario, la funzione restituirà nuovamente l'eccezione della stored procedure.

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 funzione deve restituire un valore che vogliamo inserire nella nostra tabella. Non può restituire una frase priva di significato come "stipendio okay". Inoltre, se vogliamo convalidare due colonne, abbiamo bisogno di una funzione separata per ciascuna, anche se esiste una relazione tra di esse e usiamo la stessa stored procedure per convalidarle entrambe. Buon uso per la parola chiave DETERMINISTIC.

Ecco il test: gli idraulici non possono guadagnare 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> 

... ma i manager possono (perché se lo meritano):

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> 

Nota che l'eccezione è scagliato fondamentale per questo lavoro.Non possiamo scrivere qualcosa di bizzarro SE LO STIPENDIO È VALIDO ALLORA INSERISCI la logica nella nostra dichiarazione SQL. Quindi, se la stored procedure non genera un'eccezione ma restituisce qualche stato di errore di wimpy, la funzione di wrapping dovrà interpretare l'output e lanciare la propria eccezione.

+0

In realtà la mia stored procedure fa l'inserto. Quindi non posso usare un inserto in select. –