Je travaille sur une requête (un SELECT) et j'ai besoin d'insérer le résultat de celle-ci dans un tableau. Avant de faire l'insertion, j'ai quelques vérifications à faire, et si toutes les colonnes sont valides, je ferai l'insertion.
La vérification se fait dans une procédure stockée. La même procédure est utilisée ailleurs également. Je pense donc utiliser la même procédure pour faire mes vérifications.
La procédure effectue les vérifications et insérer les valeurs est tout est OK.
J'ai essayé d'appeler la procédure dans mon SELECT mais cela ne fonctionne pas.
SELECT field1, field2, myproc(field1, field2)
from MYTABLE.
Ce type de code ne fonctionne pas.
Je pense que cela peut être fait en utilisant un curseur, mais je voudrais éviter les curseurs. Je recherche la solution la plus simple.
Quelqu'un, une idée?
utiliser une boucle PL/SQL:
BEGIN
FOR c IN (SELECT field1, field2 FROM mytable) LOOP
my_proc(c.field1, c.field2);
END LOOP;
END;
SQL ne peut utiliser que des fonctions dans la projection: il a besoin de quelque chose qui renvoie une valeur. Vous allez donc devoir écrire quelques fonctions. Voilà les mauvaises nouvelles. La bonne nouvelle est que vous pouvez réutiliser tout l'investissement dans vos procédures stockées.
Voici une procédure qui applique une règle commerciale tout à fait juste: seuls les managers peuvent avoir un salaire élevé.
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>
Parce que c'est une procédure, nous ne pouvons pas l'utiliser dans une instruction SELECT; nous devons l'envelopper dans une fonction. Cette fonction appelle simplement la procédure stockée. Il renvoie le paramètre d'entrée P_SAL. En d'autres termes, si le salaire est valable (selon les règles) il sera restitué. Sinon, la fonction relancera l'exception de la procédure stockée.
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 fonction doit retourner une valeur que nous voulons insérer dans notre table. Il ne peut pas renvoyer une phrase vide de sens comme "salaire correct". De plus, si nous voulons valider deux colonnes, nous avons besoin d'une fonction distincte pour chacune, même s'il existe une relation entre elles et que nous utilisons la même procédure stockée pour les valider toutes les deux. Bon usage du mot-clé DETERMINISTIC.
Voici le test: les plombiers ne peuvent pas gagner 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>
... mais les managers peuvent (parce qu'ils le méritent):
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>
Notez que l'exception lancée est cruciale pour ce travail. Nous ne pouvons pas écrire de logique SI SALAIRE IS VALIDE ALORS INSÉRER la logique dans notre instruction SQL. Donc, si la procédure stockée ne déclenche pas d'exception mais renvoie à la place un état d'erreur wimpy, la fonction d'habillage aura pour interpréter la sortie et lancer sa propre exception.
Vous ne pouvez pas utiliser de procédures stockées dans l'instruction SELECT. Vous pouvez utiliser des fonctions pour cela.
Si je comprends bien, vous appelez insert dans votre SP, alors prenez en considération que vous pouvez utiliser INSERT/UPDATE dans le corps de la fonction. Mais si vous avez besoin de faire quelques vérifications, vous pouvez utiliser une fonction qui effectuera ces vérifications et utilisera cette fonction dans votre instruction select.