获取Oracle中的调用包/过程

时间:2012-04-19 14:43:15

标签: oracle plsql

我正在Oracle 10g中编写一个日志记录过程,该过程使用以下插入写入表:

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

此过程在多个不同的包/过程中重用,但现在的方式是,程序员必须将其包/过程名称传递给日志记录过程(strPackagestrProcedure)。 / p>

我想知道Oracle中是否存在av $ view或者某些内容可以告诉我调用此过程的包/过程,从而消除了程序员传入strPackage和{{1 }}

实施例

如果我称这两个程序:

strProcedure

从这个包中:

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; 方法评估log_test / TestProc1log_test / TestProc2

3 个答案:

答案 0 :(得分: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)

答案 1 :(得分:1)

答案 2 :(得分:0)

Here是Oracle 9 utl_call_stack的实现(后端)。对于Oracle 10 and 11

另一种解决方案(使用p_stack包):

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

使用GWu's example,输出:

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版本。