0

変更の履歴を保持したいテーブルが多数あります。それぞれについて、末尾が _HISTO である 2 番目のテーブルを作成し、フィールド modtime、action、user を追加しました。

このテーブルのレコードを挿入、変更、または削除する前に、(デルファイ アプリから) 実際の値を histo テーブルにコピーして操作を実行するオラクル プロシージャを呼び出します。

私の手順は、DBA_TAB_COLUMNS を介して動的 SQL を生成し、生成された ( insert into tablename_histo ( fields s ) select fields, sysdate, 'acition', userid from table_name

トリガーがトリガーされるテーブルを選択する必要があるため、トリガーからこのプロシージャを呼び出すことはできないと言われました。これは本当ですか ?必要なものを実装することは可能ですか?

4

2 に答える 2

2

トリガーを使用して履歴を維持する場合(Oracleで履歴データを追跡する他の方法(Workspace Manager、Total Recall、Streams、Fine_Grained Auditingなど)ではなく)、トリガーで動的SQLを使用できます。ただし、動的SQLには、静的SQLと同じルールが適用されます。また、行レベルのトリガーの静的SQLでさえ、一般に、変更テーブルの例外を生成せずに、トリガーが定義されているテーブルをクエリすることはできません。

ただし、トリガーから動的SQLを呼び出すのではなく、同じデータディクショナリテーブルを使用して最初にトリガーを生成する動的SQLを作成できる可能性があります。トリガー自体は静的にとを参照し:new.column_nameます:old.column_name。もちろん、トリガーを編集するか、新しい列が追加されたときにトリガーを動的に作成するプロシージャを再実行する必要があります。おそらく、メインテーブルと履歴テーブルの両方に列を追加する必要があるため、これは一般的にそれほど大きな問題ではありません。

于 2012-09-25T18:46:52.797 に答える
0

Oracle では、トリガーが定義されているテーブルに対してトリガーが SELECT を実行することは許可されていません。試してみると、恐ろしい「mutating table」エラー (ORA-04091) が発生します。このエラーを回避する方法はありますがほとんど価値がないために多くの複雑さが追加されます。テーブルが更新されるたびに動的クエリを本当に作成したい場合 (IMO これはパフォーマンスの観点からは悪い考えです - メタデータクエリはしばしば遅いことがわかりますが、YMMV) のようになります。

strAction := CASE
               WHEN INSERTING THEN 'INSERT'
               WHEN UPDATING THEN 'UPDATE'
               WHEN DELETING THEN 'DELETE'
             END;

INSERT INTO TABLENAME_HISTO
  (ACTIVITY_DATE, ACTION, MTC_USER,
   old_field1, new_field1, old_field2, new_field2)
VALUES
  (SYSDATE, strAction, USERID,
   :OLD.field1, :NEW.field1, :OLD.field2, :NEW.field2)

共有してお楽しみください。

于 2012-09-26T11:22:10.953 に答える