3

私はいくつかのトリガー スクリプトの実装を任されており、同僚からのサンプルを参考にしています。それらでは、更新/挿入/削除にpl-sql条件を使用し、巨大な挿入ステートメントを(別のテーブルで)使用します。これらの挿入ステートメントは、値の前に new または old が付いているかどうか以外は変わりません。私は賢く、以下を使用して私のものをもう少しコンパクトにしようと思いました:

DECLARE
  vRow SATURN.SPRCMNT%ROWTYPE;

BEGIN

  IF UPDATING THEN
    vRow := :NEW;
  ELSIF INSERTING THEN
    vRow := :NEW;
  ELSIF DELETING THEN
    vRow := :OLD;
  END IF;

  -- Not the real insert statement
  INSERT INTO blah 
    (columns)
    VALUES
    (vRow.somecolumns);

END;

コンパイル システムから次の情報が返されます。

10/13  PLS-00049: bad bind variable 'NEW'
13/13  PLS-00049: bad bind variable 'NEW'
16/13  PLS-00049: bad bind variable 'OLD'

明らかに、これは好きではありません。私が試みていることを達成するものはありますか?:new と :old は真の行型ではありませんか? 本質的に同じコードを 3 回繰り返すのはばかげているように思えますが、より良い方法を見つけることはできません。地獄、トリガーのサイズにも厳しい制限があることを読んだと思います。どんな助けでも感謝します。

[編集] 考えただけですが、DECODE() 内で何らかの形で UPDATING/INSERTING キーワードを参照することは可能ですか?

たとえば、DECODE(SOMETHINGVAR, UPDATING, :NEW.column, DELETING, :OLD.column) を実行できれば、1 つのステートメントで vRow の各列の値を設定できます。

最初に DELETING をチェックして、他の 2 つのデフォルトを使用する方がよいと思います。

これは可能ですか?

4

2 に答える 2

4

いいえ、できません。 :newおよび:oldは疑似レコードであり、ローカル変数に割り当てることができる実際のレコードではありません。テーブルがオブジェクト タイプに基づいていて、他のオブジェクト:new:old同じように渡すことができる特定のオブジェクト タイプの実際のインスタンスである場合。しかし、トリガーを簡単に記述できるようにするためだけに、オブジェクトに関してテーブルを定義する価値があるとは考えにくいでしょう。

all_tab_columnsもちろん、動的 SQL を使用してデータ ディクショナリをクエリする (つまり、テーブル内の列のリストを取得する) ことによって、必要なトリガー コードを自動的に生成する PL/SQL パッケージを作成することもできます。記述する必要があると予想されるトリガーの数によっては、大量の同様のコードを記述して維持するよりも簡単な場合があります。

于 2013-10-27T06:37:33.960 に答える
4

この質問は何度も聞いたことがあり、解決策が見られなかったので、答えることにしました。

したがって、新しい行と古い行全体を渡す PL/SQL プロシージャを呼び出す、一般的な「構造に依存しない」トリガーを 1 つ持つという考え方です。

そのためにオブジェクトテーブルを使用しました。

create or replace type test_table_type as object(
  ... your attributes ....
);

create table test of test_table_type;

create or replace trigger trg_test_upd
before update on test
for each row
  l_new_row  test_table_type;
  l_old_row  test_table_type;
  l_row_id   raw(40000);
begin
  l_new_row := :new.sys_nc_rowinfo$; -- <-- this is your new row
  l_old_row := :old.sys_nc_rowinfo$; -- <-- this is your old row
  l_row_id :=  :old.sys_nc_oid$; -- <-- this your row logical ID (not rowid!!!). You can use it if you don't have primary key or it is composite.
  -- here you can do what ever you want with you old/new rows.
  ...
end;
/

基本型で共通の属性を定義し、この型から他の型を継承できるため、この方法が気に入っています。したがって、同じ基本型に基づく多くのテーブルに対してもジェネリック コードを使用できます。

于 2014-10-13T15:21:10.220 に答える