1

監査ログを保持するテーブルにトリガーを作成しました。新しいエントリが挿入されたら、新しいレコードをテーブル内の最新の既存のレコード (一致する ID) と列ごとに比較したいと考えています。1 つの列の値が変更された場合、insert ステートメントを別のテーブルに実行したいと考えています。次の PL SQL プロシージャを作成しました。

CREATE OR REPLACE
TRIGGER PROJECT_BASELINE_ATTR_AUD_BI BEFORE INSERT
ON PROJECT_BASELINE_ATTR_AUD 
FOR EACH ROW
DECLARE 
  tab_name constant varchar2(32) := 'PROJECT_BASELINE_ATTR_AUD';
  col_name varchar2(32);
  v_latest_row PROJECT_BASELINE_ATTR_AUD%rowtype;
BEGIN
  -- get the record to compare with
  EXECUTE IMMEDIATE 'select * from  '||tab_name||
            ' where rev = (select max(rev) from '||tab_name||' where id = '|| :new.ID ||')' into v_latest_row;
FOR x IN (SELECT DISTINCT(COLUMN_NAME) FROM ALL_TAB_COLUMNS WHERE TABLE_NAME = upper(tab_name)) 
  LOOP
  BEGIN
    col_name := x.column_name;
    -- do insert if the values are unequal
    -- IF :new.col_name <> v_latest_row.col_name
    --   INSERT INTO AUD_CHANGE_LOG VALUES (AUD_CHANGE_LOG_ID_SEQ.nextVal, :new.ID, :new.REV, tab_name, col_name);
  END;
  END LOOP;
END;

私はこれを実際の列名で実装できることを知っています。

IF :new.FOO <> v_latest_row.FOO
IF :new.BAR <> v_latest_row.BAR
...

しかし、そうでなければカスケードする場合、これは長くなります。何か案は?

4

3 に答える 3

1

トリガーの新旧の値を動的に参照する方法はありません。

必要なテーブル構造ごとにトリガーを動的に定義するシステムを開発することもできますが、それはとにかく大変な作業です。

私はそのようなことをしました、そしてそれはあなたが数日で終えることができるようなものではありません。

于 2012-07-16T18:53:26.920 に答える
0

列名を動的に参照できないというAlessandroに同意します。それぞれを手動で挿入する必要があります。個人的には、この種の複雑なロジックは、トリガーで直接実行するのではなく、コンパイルされたプロシージャで実行するのが最適だと思います。Feuersteinも同意します。

したがって、新しいテーブル行をストアドプロシージャに渡し、WHERE句に新しい列の値を配置することで、各列を監査テーブルと比較するという手間のかかる作業を実行させます。

于 2012-07-20T16:54:29.660 に答える
-1

はい。変更テーブル エラーは、操作が同じテーブルに対して発生した場合にのみ発生します。

監査テーブルのトリガーのように見えるものについて、私が知っている列ごとの比較を回避する方法はないと思います。

于 2012-07-16T14:25:04.407 に答える