web-dev-qa-db-ja.com

Oracleが選択内のストアドプロシージャを呼び出す

クエリ(SELECT)に取り組んでおり、このクエリの結果をテーブルに挿入する必要があります。挿入を行う前に、いくつかのチェックを行います。すべての列が有効な場合は、挿入を行います。

チェックはストアドプロシージャで行われます。同じ手順が他の場所でも使用されています。したがって、私は同じ手順を使用してチェックを行うことを考えています。

プロシージャはチェックを実行し、値を挿入しても問題ありません。

SELECT内でプロシージャを呼び出そうとしましたが、機能しません。

SELECT field1, field2, myproc(field1, field2)

from MYTABLE.

この種のコードは機能しません。

カーソルでできると思いますが、カーソルは避けたいです。私は最も簡単な解決策を探しています。

誰か、どんなアイデア?

15
CC.

pL/SQLループを使用します。

BEGIN
   FOR c IN (SELECT field1, field2 FROM mytable) LOOP
       my_proc(c.field1, c.field2);
   END LOOP;
END;
29
Vincent Malgrat

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ロジックを書き込むことはできません。そのため、ストアドプロシージャが例外を発生させず、代わりに弱っぽいエラーステータスを返す場合、ラッピング関数は出力を解釈し、独自の例外を投げます。

6
APC

SELECTステートメントではストアドプロシージャを使用できません。そのための関数を使用できます。

私はあなたがSPで挿入を呼び出していることを理解しているので、関数本体でINSERT/UPDATEを使用できることを考慮してください。しかし、いくつかのチェックを行う必要がある場合は、そのチェックを行い、selectステートメントでその関数を使用する関数を使用できます。

0
Incognito