クエリ(SELECT)に取り組んでおり、このクエリの結果をテーブルに挿入する必要があります。挿入を行う前に、いくつかのチェックを行います。すべての列が有効な場合は、挿入を行います。
チェックはストアドプロシージャで行われます。同じ手順が他の場所でも使用されています。したがって、私は同じ手順を使用してチェックを行うことを考えています。
プロシージャはチェックを実行し、値を挿入しても問題ありません。
SELECT内でプロシージャを呼び出そうとしましたが、機能しません。
SELECT field1, field2, myproc(field1, field2)
from MYTABLE.
この種のコードは機能しません。
カーソルでできると思いますが、カーソルは避けたいです。私は最も簡単な解決策を探しています。
誰か、どんなアイデア?
pL/SQLループを使用します。
BEGIN
FOR c IN (SELECT field1, field2 FROM mytable) LOOP
my_proc(c.field1, c.field2);
END LOOP;
END;
SQLはプロジェクション内の関数のみを使用できます。値を返す何かが必要です。したがって、いくつかの関数を作成する必要があります。それは悪い知らせです。朗報は、ストアドプロシージャへの投資をすべて再利用できることです。
完全に正義のビジネスルールを適用する手順を次に示します。マネージャーのみが高い給与を持つことができます。
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>
これはプロシージャであるため、SELECTステートメントでは使用できません。それを関数にラップする必要があります。この関数は、ストアドプロシージャを呼び出すだけです。入力パラメーターP_SALを返します。つまり、給与が有効な場合(ルールに従って)、その給与が返されます。それ以外の場合、関数はストアドプロシージャの例外を再度投げます。
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>
関数は、テーブルに挿入する値を返す必要があります。 「給与大丈夫」のような意味のない語句を返すことはできません。また、2つの列を検証する場合は、それらの間に関係があり、同じストアドプロシージャを使用して両方を検証する場合でも、それぞれに個別の関数が必要です。 DETERMINISTICキーワードの適切な使用。
これがテストです。配管工は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>
...しかし、マネージャーは(それに値するため)次のことができます。
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>
投げ出された例外は、この作業にとって重要であることに注意してください。 SQLステートメントに奇妙なIF SALARY IS VALID THEN INSERTロジックを書き込むことはできません。そのため、ストアドプロシージャが例外を発生させず、代わりに弱っぽいエラーステータスを返す場合、ラッピング関数は出力を解釈し、独自の例外を投げます。
SELECTステートメントではストアドプロシージャを使用できません。そのための関数を使用できます。
私はあなたがSPで挿入を呼び出していることを理解しているので、関数本体でINSERT/UPDATEを使用できることを考慮してください。しかし、いくつかのチェックを行う必要がある場合は、そのチェックを行い、selectステートメントでその関数を使用する関数を使用できます。