有没有办法获取包中当前正在执行的过程的名称?
create or replace package test_pkgas procedure proc1;end test_pkg;create or replace package body test_pkgas procedure proc1 is -- // Get the Procedure Name here?? // end proc1;end test_pkg;
create or replace package test_pkg
as
procedure proc1;
end test_pkg;
create or replace package body test_pkg
procedure proc1
is
-- // Get the Procedure Name here?? //
end proc1;
ssgvzors1#
在12c中,当前的子程序名称只是:
utl_call_stack.subprogram(1)(2);
目前的套餐也可以从
utl_call_stack.subprogram(1)(1);
但通常更容易仅使用$$plsql_unit。您也可以获得限定名(package.procedure):
$$plsql_unit
package.procedure
utl_call_stack.concatenate_subprogram(utl_call_stack.subprogram(1));
然而,我想不出任何情况下,一个过程或函数(或对象方法)会想要自己的名字。此功能在日志记录过程中最有用,在这种情况下 '谁叫我?' 代码应该在日志记录器中,而不是在调用它的每个事物中重复。因此,我强烈建议避免任何 '我是谁?' 程序中的逻辑。相反,将类似这样的东西放在日志记录器中(需要12个。1或更高版本):
create or replace procedure logdemoas -- This is a package name, standalone function name, standalone procedure name, -- or "__anonymous_block". k_calling_subprogram1 varchar2(128); -- This is a package procedure name or package function name, and it is NULL if -- the parent is a standalone function, standalone procedure, or anonymous block. k_calling_subprogram2 varchar2(128);begin k_calling_subprogram1 := utl_call_stack.subprogram(2)(1); begin k_calling_subprogram2 := utl_call_stack.subprogram(2)(2); exception when subscript_beyond_count then k_calling_subprogram2 := null; end; dbms_output.put_line ( $$plsql_unit || ' called from subprogram1 '||k_calling_subprogram1 ||', subprogram2 '||k_calling_subprogram2 );end logdemo;/
create or replace procedure logdemo
-- This is a package name, standalone function name, standalone procedure name,
-- or "__anonymous_block".
k_calling_subprogram1 varchar2(128);
-- This is a package procedure name or package function name, and it is NULL if
-- the parent is a standalone function, standalone procedure, or anonymous block.
k_calling_subprogram2 varchar2(128);
begin
k_calling_subprogram1 := utl_call_stack.subprogram(2)(1);
k_calling_subprogram2 := utl_call_stack.subprogram(2)(2);
exception when subscript_beyond_count then
k_calling_subprogram2 := null;
end;
dbms_output.put_line
( $$plsql_unit ||
' called from subprogram1 '||k_calling_subprogram1
||', subprogram2 '||k_calling_subprogram2 );
end logdemo;
/
不幸的是,在11g中它有点复杂,因为你必须解析dbms_utility.format_call_stack,并且因为这只给你包名和行号(在换行符分隔的文本字符串中),然后你必须查询all_source来找到子程序名。我可以张贴一些11g代码,如果你澄清它的用途。在我的11g logger中,我发现根据sqlcode等捕获dbms_utility.format_error_backtrace和dbms_utility.format_call_stack很有用,所以有一堆特定于日志记录的逻辑,如果你只是想捕获当前过程名,你可能不需要这些逻辑。
dbms_utility.format_call_stack
all_source
sqlcode
dbms_utility.format_error_backtrace
bq9c1y662#
如果它是一个独立的程序(i.即不是包内的那个),你会很容易得到答案:
SQL> create or replace procedure p_test is 2 begin 3 dbms_output.put_line('I am ' || $$plsql_unit); 4 null; 5 end; 6 /Procedure created.SQL> exec p_testI am P_TESTPL/SQL procedure successfully completed.SQL>
SQL> create or replace procedure p_test is
2 begin
3 dbms_output.put_line('I am ' || $$plsql_unit);
4 null;
5 end;
6 /
Procedure created.
SQL> exec p_test
I am P_TEST
PL/SQL procedure successfully completed.
SQL>
对于包来说,事情不再那么简单了。上面的选项(使用$$plsql_unit)返回的是包体名称,而不是过程名称:
SQL> create or replace package pkg_test as 2 procedure p_test_in_pkg; 3 end; 4 /Package created.SQL> create or replace package body pkg_test as 2 procedure p_test_in_pkg is 3 begin 4 dbms_output.put_line('Packaged procedure whose name is ' || $$plsql_unit); 5 null; 6 end; 7 end; 8 /Package body created.SQL> exec pkg_test.p_test_in_pkg;Packaged procedure whose name is PKG_TEST --> should have been "p_test_in_pkg"PL/SQL procedure successfully completed.
SQL> create or replace package pkg_test as
2 procedure p_test_in_pkg;
3 end;
4 /
Package created.
SQL> create or replace package body pkg_test as
2 procedure p_test_in_pkg is
3 begin
4 dbms_output.put_line('Packaged procedure whose name is ' || $$plsql_unit);
5 null;
6 end;
7 end;
8 /
Package body created.
SQL> exec pkg_test.p_test_in_pkg;
Packaged procedure whose name is PKG_TEST --> should have been "p_test_in_pkg"
以下功能似乎正在工作。作者是 garbuya,来源是OTN论坛的讨论Efficient WHO_AM_I and WHO_CALLED_ME讨论(2010年)。
create or replaceFUNCTION FN_WHO_AM_I ( p_lvl NUMBER DEFAULT 0) RETURN VARCHAR2IS/***********************************************************************************************FN_WHO_AM_I returns the full ORACLE name of your object including schema and package names--FN_WHO_AM_I(0) - returns the name of your objectFN_WHO_AM_I(1) - returns the name of calling objectFN_WHO_AM_I(2) - returns the name of object, who called calling objectetc., etc., etc.... Up to to he highest level-------------------------------------------------------------------------------------------------Copyrigth GARBUYA 2010*************************************************************************************************/TYPE str_varr_t IS VARRAY(2) OF CHAR(1);TYPE str_table_t IS TABLE OF VARCHAR2(256);TYPE num_table_t IS TABLE OF NUMBER;v_stack VARCHAR2(2048) DEFAULT UPPER(dbms_utility.format_call_stack);v_tmp_1 VARCHAR2(1024);v_tmp_2 VARCHAR2(1024);v_pkg_name VARCHAR2(32);v_obj_type VARCHAR2(32);v_owner VARCHAR2(32);v_idx NUMBER := 0;v_pos1 NUMBER := 0;v_pos2 NUMBER := 0;v_line_nbr NUMBER := 0;v_blk_cnt NUMBER := 0;v_str_len NUMBER := 0;v_bgn_cnt NUMBER := 0;v_end_cnt NUMBER := 0;it_is_comment BOOLEAN := FALSE;it_is_literal BOOLEAN := FALSE;v_literal_arr str_varr_t := str_varr_t ('''', '"');v_blk_bgn_tbl str_table_t := str_table_t (' IF ' , ' LOOP ' , ' CASE ', ' BEGIN ');v_tbl str_table_t := str_table_t();v_blk_bgn_len_tbl num_table_t := num_table_t();BEGIN v_stack := SUBSTR(v_stack,INSTR(v_stack,CHR(10),INSTR(v_stack,'FN_WHO_AM_I'))+1)||'ORACLE'; -- skip myself FOR v_pos2 in 1 .. p_lvl LOOP -- advance to the input level v_pos1 := INSTR(v_stack, CHR(10)); v_stack := SUBSTR(v_stack, INSTR(v_stack, CHR(10)) + 1); END LOOP; v_pos1 := INSTR(v_stack, CHR(10)); IF v_pos1 = 0 THEN RETURN (v_stack); END IF; v_stack := SUBSTR(v_stack, 1, v_pos1 - 1); -- get only current level v_stack := TRIM(SUBSTR(v_stack, instr(v_stack, ' '))); -- cut object handle v_line_nbr := TO_NUMBER(SUBSTR(v_stack, 1, instr(v_stack, ' ') - 1)); -- get line number v_stack := TRIM(SUBSTR(v_stack, instr(v_stack, ' '))); -- cut line number v_pos1 := INSTR(v_stack, ' BODY'); IF v_pos1 = 0 THEN RETURN (v_stack); END IF; v_pos1 := INSTR(v_stack, ' ', v_pos1 + 2); -- find end of object type v_obj_type := SUBSTR(v_stack, 1, v_pos1 - 1); -- get object type v_stack := TRIM(SUBSTR(v_stack, v_pos1 + 1)); -- get package name v_pos1 := INSTR(v_stack, '.'); v_owner := SUBSTR(v_stack, 1, v_pos1 - 1); -- get owner v_pkg_name := SUBSTR(v_stack, v_pos1 + 1); -- get package name v_blk_cnt := 0; it_is_literal := FALSE; -- FOR v_idx in v_blk_bgn_tbl.FIRST .. v_blk_bgn_tbl.LAST LOOP v_blk_bgn_len_tbl.EXTEND(1); v_blk_bgn_len_tbl (v_blk_bgn_len_tbl.last) := LENGTH(v_blk_bgn_tbl(v_idx)); END LOOP; -- FOR src IN ( SELECT ' '||REPLACE(TRANSLATE(UPPER(text), ';('||CHR(10), ' '),'''''',' ') ||' ' text FROM all_source where owner = v_owner and name = v_pkg_name and type = v_obj_type and line < v_line_nbr ORDER BY line ) LOOP v_stack := src.text; IF it_is_comment THEN v_pos1 := INSTR (v_stack, '*/'); IF v_pos1 > 0 THEN v_stack := SUBSTR (v_stack, v_pos1 + 2); it_is_comment := FALSE; ELSE v_stack := ' '; END IF; END IF; -- IF v_stack != ' ' THEN -- v_pos1 := INSTR (v_stack, '/*'); WHILE v_pos1 > 0 LOOP v_tmp_1 := SUBSTR (v_stack, 1, v_pos1 - 1); v_pos2 := INSTR (v_stack, '*/'); IF v_pos2 > 0 THEN v_tmp_2 := SUBSTR (v_stack, v_pos2 + 2); v_stack := v_tmp_1||v_tmp_2; ELSE v_stack := v_tmp_1; it_is_comment := TRUE; END IF; v_pos1 := INSTR (v_stack, '/*'); END LOOP; -- IF v_stack != ' ' THEN v_pos1 := INSTR (v_stack, '--'); IF v_pos1 > 0 THEN v_stack := SUBSTR (v_stack, 1, v_pos1 - 1); END IF; -- IF v_stack != ' ' THEN FOR v_idx in v_literal_arr.FIRST .. v_literal_arr.LAST LOOP v_pos1 := INSTR (v_stack, v_literal_arr (v_idx) ); WHILE v_pos1 > 0 LOOP v_pos2 := INSTR (v_stack, v_literal_arr (v_idx), v_pos1 + 1); IF v_pos2 > 0 THEN v_tmp_1 := SUBSTR (v_stack, 1, v_pos1 - 1); v_tmp_2 := SUBSTR (v_stack, v_pos2 + 1); v_stack := v_tmp_1||v_tmp_2; ELSE IF it_is_literal THEN v_stack := SUBSTR (v_stack, v_pos1 + 1); it_is_literal := FALSE; ELSE v_stack := SUBSTR (v_stack, 1, v_pos1 - 1); it_is_literal := TRUE; END IF; END IF; v_pos1 := INSTR (v_stack, v_literal_arr (v_idx) ); END LOOP; END LOOP; -- IF v_stack != ' ' THEN WHILE INSTR (v_stack, ' ') > 0 LOOP v_stack := REPLACE(v_stack, ' ', ' '); END LOOP; v_stack := REPLACE(v_stack, ' END IF ', ' END '); v_stack := REPLACE(v_stack, ' END LOOP ', ' END '); -- IF v_stack != ' ' THEN v_stack := ' '||v_stack; v_pos1 := INSTR(v_stack, ' FUNCTION ') + INSTR(v_stack, ' PROCEDURE '); IF v_pos1 > 0 THEN v_obj_type := TRIM(SUBSTR(v_stack, v_pos1 + 1, 9)); -- get object type v_stack := TRIM(SUBSTR(v_stack, v_pos1 + 10))||' '; -- cut object type v_stack := SUBSTR(v_stack, 1, INSTR(v_stack, ' ') - 1 ); -- get object name v_tbl.EXTEND(1); v_tbl (v_tbl.last) := v_obj_type||' '||v_owner||'.'||v_pkg_name||'.'||v_stack; END IF; -- v_pos1 := 0; v_pos2 := 0; v_tmp_1 := v_stack; v_tmp_2 := v_stack; FOR v_idx in v_blk_bgn_tbl.FIRST .. v_blk_bgn_tbl.LAST LOOP v_str_len := NVL(LENGTH(v_tmp_1),0); v_tmp_1 := REPLACE(v_tmp_1,v_blk_bgn_tbl(v_idx), NULL); v_bgn_cnt := NVL(LENGTH(v_tmp_1), 0); v_pos1 := v_pos1 + (v_str_len - v_bgn_cnt)/v_blk_bgn_len_tbl(v_idx); v_str_len := NVL(LENGTH(v_tmp_2),0); v_tmp_2 := REPLACE(v_tmp_2,' END ', NULL); v_end_cnt := NVL(LENGTH(v_tmp_2), 0); v_pos2 := v_pos2 + (v_str_len - v_end_cnt)/5; --- 5 is the length(' END ') END LOOP; IF v_pos1 > v_pos2 THEN v_blk_cnt := v_blk_cnt + 1; ELSIF v_pos1 < v_pos2 THEN v_blk_cnt := v_blk_cnt - 1; IF v_blk_cnt = 0 AND v_tbl.COUNT > 0 THEN v_tbl.DELETE(v_tbl.last); END IF; END IF; END IF; END IF; END IF; END IF; END IF; END LOOP; RETURN CASE v_tbl.COUNT WHEN 0 THEN 'UNKNOWN' ELSE v_tbl(v_tbl.LAST) END;END;/
create or replace
FUNCTION FN_WHO_AM_I ( p_lvl NUMBER DEFAULT 0) RETURN VARCHAR2
IS
/***********************************************************************************************
FN_WHO_AM_I returns the full ORACLE name of your object including schema and package names
--
FN_WHO_AM_I(0) - returns the name of your object
FN_WHO_AM_I(1) - returns the name of calling object
FN_WHO_AM_I(2) - returns the name of object, who called calling object
etc., etc., etc.... Up to to he highest level
-------------------------------------------------------------------------------------------------
Copyrigth GARBUYA 2010
*************************************************************************************************/
TYPE str_varr_t IS VARRAY(2) OF CHAR(1);
TYPE str_table_t IS TABLE OF VARCHAR2(256);
TYPE num_table_t IS TABLE OF NUMBER;
v_stack VARCHAR2(2048) DEFAULT UPPER(dbms_utility.format_call_stack);
v_tmp_1 VARCHAR2(1024);
v_tmp_2 VARCHAR2(1024);
v_pkg_name VARCHAR2(32);
v_obj_type VARCHAR2(32);
v_owner VARCHAR2(32);
v_idx NUMBER := 0;
v_pos1 NUMBER := 0;
v_pos2 NUMBER := 0;
v_line_nbr NUMBER := 0;
v_blk_cnt NUMBER := 0;
v_str_len NUMBER := 0;
v_bgn_cnt NUMBER := 0;
v_end_cnt NUMBER := 0;
it_is_comment BOOLEAN := FALSE;
it_is_literal BOOLEAN := FALSE;
v_literal_arr str_varr_t := str_varr_t ('''', '"');
v_blk_bgn_tbl str_table_t := str_table_t (' IF ' , ' LOOP ' , ' CASE ', ' BEGIN ');
v_tbl str_table_t := str_table_t();
v_blk_bgn_len_tbl num_table_t := num_table_t();
BEGIN
v_stack := SUBSTR(v_stack,INSTR(v_stack,CHR(10),INSTR(v_stack,'FN_WHO_AM_I'))+1)||'ORACLE'; -- skip myself
FOR v_pos2 in 1 .. p_lvl LOOP -- advance to the input level
v_pos1 := INSTR(v_stack, CHR(10));
v_stack := SUBSTR(v_stack, INSTR(v_stack, CHR(10)) + 1);
END LOOP;
IF v_pos1 = 0 THEN
RETURN (v_stack);
END IF;
v_stack := SUBSTR(v_stack, 1, v_pos1 - 1); -- get only current level
v_stack := TRIM(SUBSTR(v_stack, instr(v_stack, ' '))); -- cut object handle
v_line_nbr := TO_NUMBER(SUBSTR(v_stack, 1, instr(v_stack, ' ') - 1)); -- get line number
v_stack := TRIM(SUBSTR(v_stack, instr(v_stack, ' '))); -- cut line number
v_pos1 := INSTR(v_stack, ' BODY');
v_pos1 := INSTR(v_stack, ' ', v_pos1 + 2); -- find end of object type
v_obj_type := SUBSTR(v_stack, 1, v_pos1 - 1); -- get object type
v_stack := TRIM(SUBSTR(v_stack, v_pos1 + 1)); -- get package name
v_pos1 := INSTR(v_stack, '.');
v_owner := SUBSTR(v_stack, 1, v_pos1 - 1); -- get owner
v_pkg_name := SUBSTR(v_stack, v_pos1 + 1); -- get package name
v_blk_cnt := 0;
it_is_literal := FALSE;
FOR v_idx in v_blk_bgn_tbl.FIRST .. v_blk_bgn_tbl.LAST
LOOP
v_blk_bgn_len_tbl.EXTEND(1);
v_blk_bgn_len_tbl (v_blk_bgn_len_tbl.last) := LENGTH(v_blk_bgn_tbl(v_idx));
FOR src
IN ( SELECT ' '||REPLACE(TRANSLATE(UPPER(text), ';('||CHR(10), ' '),'''''',' ') ||' ' text
FROM all_source
where owner = v_owner
and name = v_pkg_name
and type = v_obj_type
and line < v_line_nbr
ORDER BY line
)
v_stack := src.text;
IF it_is_comment THEN
v_pos1 := INSTR (v_stack, '*/');
IF v_pos1 > 0 THEN
v_stack := SUBSTR (v_stack, v_pos1 + 2);
it_is_comment := FALSE;
ELSE
v_stack := ' ';
IF v_stack != ' ' THEN
v_pos1 := INSTR (v_stack, '/*');
WHILE v_pos1 > 0 LOOP
v_tmp_1 := SUBSTR (v_stack, 1, v_pos1 - 1);
v_pos2 := INSTR (v_stack, '*/');
IF v_pos2 > 0 THEN
v_tmp_2 := SUBSTR (v_stack, v_pos2 + 2);
v_stack := v_tmp_1||v_tmp_2;
v_stack := v_tmp_1;
it_is_comment := TRUE;
v_pos1 := INSTR (v_stack, '--');
v_stack := SUBSTR (v_stack, 1, v_pos1 - 1);
FOR v_idx in v_literal_arr.FIRST .. v_literal_arr.LAST
v_pos1 := INSTR (v_stack, v_literal_arr (v_idx) );
v_pos2 := INSTR (v_stack, v_literal_arr (v_idx), v_pos1 + 1);
v_tmp_2 := SUBSTR (v_stack, v_pos2 + 1);
IF it_is_literal THEN
v_stack := SUBSTR (v_stack, v_pos1 + 1);
it_is_literal := TRUE;
WHILE INSTR (v_stack, ' ') > 0
v_stack := REPLACE(v_stack, ' ', ' ');
v_stack := REPLACE(v_stack, ' END IF ', ' END ');
v_stack := REPLACE(v_stack, ' END LOOP ', ' END ');
v_stack := ' '||v_stack;
v_pos1 := INSTR(v_stack, ' FUNCTION ') + INSTR(v_stack, ' PROCEDURE ');
v_obj_type := TRIM(SUBSTR(v_stack, v_pos1 + 1, 9)); -- get object type
v_stack := TRIM(SUBSTR(v_stack, v_pos1 + 10))||' '; -- cut object type
v_stack := SUBSTR(v_stack, 1, INSTR(v_stack, ' ') - 1 ); -- get object name
v_tbl.EXTEND(1);
v_tbl (v_tbl.last) := v_obj_type||' '||v_owner||'.'||v_pkg_name||'.'||v_stack;
v_pos1 := 0;
v_pos2 := 0;
v_tmp_1 := v_stack;
v_tmp_2 := v_stack;
v_str_len := NVL(LENGTH(v_tmp_1),0);
v_tmp_1 := REPLACE(v_tmp_1,v_blk_bgn_tbl(v_idx), NULL);
v_bgn_cnt := NVL(LENGTH(v_tmp_1), 0);
v_pos1 := v_pos1 + (v_str_len - v_bgn_cnt)/v_blk_bgn_len_tbl(v_idx);
v_str_len := NVL(LENGTH(v_tmp_2),0);
v_tmp_2 := REPLACE(v_tmp_2,' END ', NULL);
v_end_cnt := NVL(LENGTH(v_tmp_2), 0);
v_pos2 := v_pos2 + (v_str_len - v_end_cnt)/5; --- 5 is the length(' END ')
IF v_pos1 > v_pos2 THEN
v_blk_cnt := v_blk_cnt + 1;
ELSIF v_pos1 < v_pos2 THEN
v_blk_cnt := v_blk_cnt - 1;
IF v_blk_cnt = 0 AND v_tbl.COUNT > 0 THEN
v_tbl.DELETE(v_tbl.last);
RETURN CASE v_tbl.COUNT WHEN 0 THEN 'UNKNOWN' ELSE v_tbl(v_tbl.LAST) END;
END;
测试:
SQL> create or replace package body pkg_test as 2 procedure p_test_in_pkg is 3 begin 4 dbms_output.put_line('Packaged procedure, using $$plsql_unit = ' || $$plsql_unit); 5 dbms_output.put_line('FN_WHO_AM_I = ' || fn_who_am_i); 6 null; 7 end; 8 end; 9 /Package body created.SQL> exec pkg_test.p_test_in_pkg;Packaged procedure, using $$plsql_unit = PKG_TEST --> this one is wrong (package body name) ...FN_WHO_AM_I = PROCEDURE SCOTT.PKG_TEST.P_TEST_IN_PKG --> ... but this one is OKPL/SQL procedure successfully completed.SQL>
4 dbms_output.put_line('Packaged procedure, using $$plsql_unit = ' || $$plsql_unit);
5 dbms_output.put_line('FN_WHO_AM_I = ' || fn_who_am_i);
6 null;
8 end;
9 /
Packaged procedure, using $$plsql_unit = PKG_TEST --> this one is wrong (package body name) ...
FN_WHO_AM_I = PROCEDURE SCOTT.PKG_TEST.P_TEST_IN_PKG --> ... but this one is OK
jgovgodb3#
一种方法使用从这里借用的想法:http://www.orafaq.com/forum/t/173023/
注意:这只适用于Oracle 12c。对于11g,它只给出了包名称。
创建一个名为show_caller的过程。这使用了OWA_UTIL.WHO_CALLED_ME过程。
show_caller
OWA_UTIL.WHO_CALLED_ME
create or replace procedure show_calleras l_owner varchar2(200); l_name varchar2(200); l_lineno number; l_caller varchar2(200);begin OWA_UTIL.WHO_CALLED_ME (l_owner, l_name,l_lineno,l_caller); dbms_output.put_line('Inside '||l_name);end;/
create or replace procedure show_caller
l_owner varchar2(200);
l_name varchar2(200);
l_lineno number;
l_caller varchar2(200);
OWA_UTIL.WHO_CALLED_ME (l_owner, l_name,l_lineno,l_caller);
dbms_output.put_line('Inside '||l_name);
现在,你可以把你的包写成:
CREATE OR replace PACKAGE test_pkg AS PROCEDURE proc1; END test_pkg; / CREATE OR replace PACKAGE BODY test_pkg AS PROCEDURE Proc1 AS BEGIN show_caller; -- proc1 calls show_caller END proc1; END test_pkg; /
CREATE OR replace PACKAGE test_pkg
AS
PROCEDURE proc1;
END test_pkg;
CREATE OR replace PACKAGE BODY test_pkg
PROCEDURE Proc1
show_caller; -- proc1 calls show_caller
END proc1;
处决
SET SERVEROUTPUT ONBEGIN Test_pkg.Proc1;END;/Inside TEST_PKG.PROC1
SET SERVEROUTPUT ON
Test_pkg.Proc1;
Inside TEST_PKG.PROC1
请注意,这将打印过程的名称。如果要将其作为变量使用,则将l_name(如果需要,还可以与其他变量沿着)作为OUT变量从show_caller传递Live SQL Demo(需要免费OTN帐户)另一种选择是在过程中使用OWA_UTIL.GET_PROCEDURE函数:但在这种情况下似乎不适合我我很乐意从Maven那里了解更多。
l_name
OUT
OWA_UTIL.GET_PROCEDURE
suzh9iv84#
我的快速样本:
create or replace package body MyPackage as procedure PrintMethodName is ThisMethod#FullName varchar2(128) := regexp_substr( dbms_utility.format_call_stack, 'package\s+body\s+([^[:space:]]+)', 1,1,'i',1); -- schema.package.method ThisMethod#CurrentSchemaName varchar2(128) := regexp_substr( regexp_substr( dbms_utility.format_call_stack, 'package\s+body\s+([^[:space:]]+)', 1,1,'i',1), '[^.]+[.][^.]+$'); -- package.method ThisMethod#MethodName varchar2(128) := regexp_substr( regexp_substr( dbms_utility.format_call_stack, 'package\s+body\s+([^[:space:]]+)', 1,1,'i',1), '[^.]+$'); -- method begin dbms_output.put_line(dbms_utility.format_call_stack); dbms_output.put_line(ThisMethod#FullName); dbms_output.put_line(ThisMethod#CurrentSchemaName); dbms_output.put_line(ThisMethod#MethodName); end;end;/
create or replace package body MyPackage as
procedure PrintMethodName is
ThisMethod#FullName varchar2(128) := regexp_substr(
dbms_utility.format_call_stack,
'package\s+body\s+([^[:space:]]+)',
1,1,'i',1); -- schema.package.method
ThisMethod#CurrentSchemaName varchar2(128) := regexp_substr(
regexp_substr(
1,1,'i',1),
'[^.]+[.][^.]+$'); -- package.method
ThisMethod#MethodName varchar2(128) := regexp_substr(
'[^.]+$'); -- method
dbms_output.put_line(dbms_utility.format_call_stack);
dbms_output.put_line(ThisMethod#FullName);
dbms_output.put_line(ThisMethod#CurrentSchemaName);
dbms_output.put_line(ThisMethod#MethodName);
4条答案
按热度按时间ssgvzors1#
在12c中,当前的子程序名称只是:
目前的套餐也可以从
但通常更容易仅使用
$$plsql_unit
。您也可以获得限定名(package.procedure
):然而,我想不出任何情况下,一个过程或函数(或对象方法)会想要自己的名字。此功能在日志记录过程中最有用,在这种情况下 '谁叫我?' 代码应该在日志记录器中,而不是在调用它的每个事物中重复。因此,我强烈建议避免任何 '我是谁?' 程序中的逻辑。相反,将类似这样的东西放在日志记录器中(需要12个。1或更高版本):
不幸的是,在11g中它有点复杂,因为你必须解析
dbms_utility.format_call_stack
,并且因为这只给你包名和行号(在换行符分隔的文本字符串中),然后你必须查询all_source
来找到子程序名。我可以张贴一些11g代码,如果你澄清它的用途。在我的11g logger中,我发现根据
sqlcode
等捕获dbms_utility.format_error_backtrace
和dbms_utility.format_call_stack
很有用,所以有一堆特定于日志记录的逻辑,如果你只是想捕获当前过程名,你可能不需要这些逻辑。bq9c1y662#
如果它是一个独立的程序(i.即不是包内的那个),你会很容易得到答案:
对于包来说,事情不再那么简单了。上面的选项(使用
$$plsql_unit
)返回的是包体名称,而不是过程名称:以下功能似乎正在工作。作者是 garbuya,来源是OTN论坛的讨论Efficient WHO_AM_I and WHO_CALLED_ME讨论(2010年)。
测试:
jgovgodb3#
一种方法使用从这里借用的想法:http://www.orafaq.com/forum/t/173023/
注意:这只适用于Oracle 12c。对于11g,它只给出了包名称。
创建一个名为
show_caller
的过程。这使用了OWA_UTIL.WHO_CALLED_ME
过程。现在,你可以把你的包写成:
处决
请注意,这将打印过程的名称。如果要将其作为变量使用,则将
l_name
(如果需要,还可以与其他变量沿着)作为OUT
变量从show_caller
传递Live SQL Demo(需要免费OTN帐户)
另一种选择是在过程中使用
OWA_UTIL.GET_PROCEDURE
函数:但在这种情况下似乎不适合我我很乐意从Maven那里了解更多。suzh9iv84#
我的快速样本: