4

複数のパッケージ/ストアド プロシージャが DML ステートメントを実行するテーブル (Oracle 11g) があります。トリガーを使用してテーブルに DML を発行したパッケージ/プロシージャ名をキャプチャし、ログ テーブルに記録したいと考えています。

例えば:

パッケージは、テーブルの をMY_PACK.MY_PROC()発行します。を発行したパッケージ/プロシージャ名を取得し、この情報を別のテーブルに保存できるトリガーを設計します。insert into...mytabmytabinsert into..my_tab_log

検索を行ったところ、プロシージャ名を指摘できることがわかりました$$PLSQL_UNIT$$PLSQL_LINE、これらの変数がトリガー内から使用されると、DML ステートメントを発行したパッケージ/プロシージャ名の代わりにトリガー名が取得されます。

お気に入り -

CREATE OR REPLACE TRIGGER my_trg
AFTER INSERT OR UPDATE OR DELETE
ON MY_TAB
FOR EACH ROW
BEGIN
    IF INSERTING THEN
         insert into my_tab_log values('INSERTED A ROW'
                                       sysdate,
                                       $$PLSQL_UNIT); 
    END IF;
    -- This would capture Trigger name but I would like to capture `MY_PACK.MY_PROC()`
    -- which issued the insert statement
    ...
END;

$$PLSQL_UNIT は条件付きコンパイル ディレクティブであるためです。PL/SQLコードをコンパイル/再コンパイルすると解決されます。残念ながら、トリガー内の $$PLSQL_UNIT はトリガー名にすぎず、トリガーのコンパイル時に解決されます。

手順も見つけましたowa_util.who_called_meが、これを自分のニーズに合わせて使用​​する方法について頭を悩ませることができませんでした。DMLステートメントを発行する実際のパッケージ/ストアドプロシージャを変更せずに、私が望むものを達成することさえ可能ですか? これらのプログラムを変更することはできません。これは厳しい制限であるため、オプションではありません。

4

1 に答える 1

7

$$PLSQL_UNIT パッケージ内のプロシージャの名前ではなく、パッケージ名のみを提供します。についても同様ですwho_called_me

owa_util.who_called_meは、計り知れない Kyte 氏によって書かれた小さなユーティリティに基づいています。ここで彼のソース コードを覗いてみると、ルーチンがコール スタックから情報を取得していることがわかります。したがって、それが提供する情報は次のとおりです。

  • プログラム所有者
  • プログラム名 (パッケージ、またはスタンドアロン プロシージャ)
  • プログラムの種類
  • 行番号

これらの確かに苛立たしい制限は、過負荷にかかっています。同じ名前で異なる署名を持つパッケージ化されたプロシージャを作成できます。したがって、「プロシージャー名」は、どのコードが動作しているかを識別する際に、システムにとって特に有用ではありません。

とにかく、で遊んでみたい場合は、次のwho_called_meように 4 つのパラメーターを取得します。

create or replace trigger my_trg 
before insert or update on my_tab
for each row
declare
  l_owner varchar2(30);
  l_name varchar2(30);
  l_line pls_integer;
  l_type varchar2(30);
begin
  owa_util.who_called_me(l_owner,l_name,l_line,l_type);
  IF INSERTING THEN
     insert into my_tab_log values('INSERTED A ROW'
                                   sysdate,
                                   l_owner||'.'||l_name); 
  END IF;
end;
/
于 2013-01-28T07:32:49.040 に答える