2

次の挿入を使用してテーブルに書き込むOracle10gでロギングプロシージャを作成しています。

INSERT INTO EXEC_LOG VALUES (
  (SELECT SYS_CONTEXT('USERENV','SESSIONID') sessionid FROM dual),
  strPackage, strProcedure, strEventType, strEventLevel, SYSDATE, strMessage
);

このプロシージャは複数の異なるパッケージ/プロシージャで再利用されますが、現在のように、プログラマはパッケージ/プロシージャの名前をロギングプロシージャ(strPackageおよびstrProcedure)に渡す必要があります。

Oracleに、このプロシージャがどのパッケージ/プロシージャから呼び出されたかを教えてくれるav $ビューなどがあるので、プログラマーがとを渡す必要がないのではないかと思いstrPackageますstrProcedure

例:

これらの2つの手順を呼び出すと:

BEGIN
  log_test.testproc1;
  log_test.testproc2;
END;

このパッケージから:

CREATE OR REPLACE PACKAGE BODY log_test IS
  PROCEDURE TestProc1 IS
    BEGIN
      write_exec_log( ... );    
    END TestProc1;
  PROCEDURE TestProc2 IS
    BEGIN
      write_exec_log( ... );     
    END TestProc2;  
 END log_test; 

insdieメソッドからlog_test/TestProc1およびlog_test/を評価できるようにしたいと思います。TestProc2write_exec_log

4

3 に答える 3

3

Oracle 12c 以降では、組み込みパッケージ UTL_CALL_STACK ( http://docs.oracle.com/database/121/ARPLS/u_call_stack.htm ) を使用できます。

呼び出し手順だけに興味がある場合の短い例: DBMS_OUTPUT.PUT_LINE(UTL_Call_Stack.Concatenate_Subprogram(UTL_Call_Stack.Subprogram(2)));

または、完全なコール スタックを出力するには、次のようにします。

FOR j IN REVERSE 1..UTL_Call_Stack.Dynamic_Depth() LOOP 
  DBMS_OUTPUT.PUT_LINE(UTL_Call_Stack.Concatenate_Subprogram(UTL_Call_Stack.Subprogram(j)));
END LOOP;

パッケージの例:

CREATE OR REPLACE PACKAGE  log_test IS
 PROCEDURE write_exec_log(msg VARCHAR2);
 PROCEDURE TestProc1;
 PROCEDURE TestProc2;  
 PROCEDURE TestProc3;
END log_test; 
/

CREATE OR REPLACE PACKAGE BODY log_test IS
 PROCEDURE write_exec_log(msg VARCHAR2) IS
  BEGIN
   DBMS_OUTPUT.PUT_LINE(msg);
   DBMS_OUTPUT.PUT_LINE('-- ');
   DBMS_OUTPUT.PUT_LINE('calling procedure/function: '
                      ||UTL_Call_Stack.Concatenate_Subprogram(
                                                              UTL_Call_Stack.Subprogram(2)
                                                             )
                       );
   DBMS_OUTPUT.PUT_LINE('-- ');
   DBMS_OUTPUT.PUT_LINE('Call Stack');
   FOR j IN REVERSE 1..UTL_Call_Stack.Dynamic_Depth() LOOP
    DBMS_OUTPUT.PUT_LINE(UTL_Call_Stack.Concatenate_Subprogram(
                                                               UTL_Call_Stack.Subprogram(j)
                                                              )
                        );
   END LOOP;
  END write_exec_log;
 PROCEDURE TestProc1 IS
  BEGIN
   write_exec_log( 'msg TestProc1' );    
  END TestProc1;
 PROCEDURE TestProc2 IS
  BEGIN
   write_exec_log( 'msg TestProc2' );     
  END TestProc2;  
 PROCEDURE TestProc3 IS
  BEGIN
   TestProc2;
  END TestProc3;  
END log_test; 
/

exec log_test.TestProc1
exec log_test.TestProc2
exec log_test.TestProc3

(申し訳ありませんが、sqlfiddle はありません。執筆時点では 12c はありません)

于 2015-07-16T12:52:37.390 に答える
1

Tom Kyte の Who_Called_Me が機能するはずです。

于 2012-04-19T14:51:56.323 に答える
0

utl_call_stackこれは、 Oracle 9 用の実装 (バックポート)です。Oracle 10 および 11用です。

別の解決策 ( p_stackパッケージを使用):

dbms_output.put_line( p_stack.getConcatenatedSubprograms( p_stack.whoCalledMe ) );

GWuの例では、次のように出力されます。

LOG_TEST.TESTPROC1
LOG_TEST.TESTPROC2
LOG_TEST.TESTPROC2

それらは最後の呼び出しだけです。または、完全なスタックが必要な場合:

dbms_output.put_line( p_stack.getCallStack );
dbms_output.put_line( '' );

これは次のように出力されます。

493: YOUR_SCHEMA.PACKAGE BODY P_STACK.FUNCTION GETCALLSTACK.FUNCTION GETCALLSTACK
4: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE WRITE_EXEC_LOG
9: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE TESTPROC1
2: YOUR_SCHEMA.ANONYMOUS BLOCK

493: YOUR_SCHEMA.PACKAGE BODY P_STACK.FUNCTION GETCALLSTACK.FUNCTION GETCALLSTACK
4: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE WRITE_EXEC_LOG
13: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE TESTPROC2
3: YOUR_SCHEMA.ANONYMOUS BLOCK

493: YOUR_SCHEMA.PACKAGE BODY P_STACK.FUNCTION GETCALLSTACK.FUNCTION GETCALLSTACK
4: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE WRITE_EXEC_LOG
13: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE TESTPROC2
17: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE TESTPROC3
4: YOUR_SCHEMA.ANONYMOUS BLOCK

これは、9 から 12 までの Oracle バージョンで機能します。

于 2015-12-10T12:33:59.520 に答える