4

トリガーの内部で、テーブルのすべての列をループして、新しい値を古い値と比較しようとしています。これが私がこれまでに持っているものです:

CREATE OR REPLACE TRIGGER "JOSH".TEST#UPD BEFORE 
UPDATE ON "JOSH"."TEST_TRIGGER_TABLE" REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
declare    
   oldval varchar(2000);   
   newval varchar(2000);   
begin    
   for row in (SELECT column_name from user_tab_columns where table_name='TEST_TRIGGER_TABLE') loop  
     execute immediate 'select :old.'||row.column_name||' from dual'   into oldval;  
     execute immediate 'select :new.'||row.column_name||' from dual'   into newval;  
     --Do something here with the old and new values
   end loop;  
end;

トリガーはコンパイルされますが、トリガーが起動すると、次のようになります。

ORA-01008:すべての変数がバインドされているわけではありません

の値を期待しているため、最初の実行で即時実行します:old:oldトリガーの:new一部としてすでに定義されていますが、executeimmediateはこれらの変数を認識できないようです。

トリガーの列値を動的に反復する方法はありますか?

4

4 に答える 4

5

いいえ、:old値と:new値を動的に参照することはできません。Shaneが示唆しているように、静的トリガーコードを生成するコードを記述すれば、作業が楽になります。また、「ここで何かを行う」をパッケージプロシージャにして、トリガーが次のようになるようにすることもできます。

CREATE OR REPLACE TRIGGER JOSH.TEST#UPD BEFORE 
UPDATE ON JOSH.TEST_TRIGGER_TABLE
begin    
   my_package.do_something_with (:old.col1, :new.col1);
   my_package.do_something_with (:old.col2, :new.col2);
   my_package.do_something_with (:old.col3, :new.col3);
   -- etc.
end;

(ちなみに、無意味なREFERENCING句を捨てることができます)。

于 2009-04-24T17:25:32.250 に答える
4

基本的に、テーブルへのすべての変更を監査するために独自のシステムを構築しようとしていますか?(任意の列の新旧の値で何をしているのかについての私の最善の推測です。)もしそうなら、Oracle独自の監査機能を調べたいと思うかもしれません。

于 2009-04-24T17:29:58.090 に答える
4

あなたがやろうとしていることをあなたができるかどうかはわかりません。PL / SQLコード内の表の列に明示的に名前を付けたくない理由は何ですか?表のフィールドが頻繁に変更される場合は、各表のPL /SQLトリガーを動的に作成するPL/SQLを作成できます(それぞれに明示的なフィールド名があります)。テーブルが変更されるたびに、そのPL/SQLを実行して新しいトリガーを生成できます。

于 2009-04-24T17:08:50.010 に答える
2

MSSQLでも同様の問題が発生しました。

私の解決策は、テーブルと列の情報を(ディクショナリビューまたはカスタムリポジトリを介して)繰り返し、必要なトリガーを生成するストアドプロシージャを作成することでした。この手順は、データモデルが変更された場合にのみ実行する必要があります。

利点は、更新のたびにメタモデルにカーソルを合わせる必要がなく、事前にトリガーを生成できることです。

于 2009-04-24T17:19:13.123 に答える