oracle 包中当前正在执行的过程名称

pxyaymoc  于 2023-04-29  发布在  Oracle
关注(0)|答案(4)|浏览(168)

有没有办法获取包中当前正在执行的过程的名称?

  1. create or replace package test_pkg
  2. as
  3. procedure proc1;
  4. end test_pkg;
  5. create or replace package body test_pkg
  6. as
  7. procedure proc1
  8. is
  9. -- // Get the Procedure Name here?? //
  10. end proc1;
  11. end test_pkg;
ssgvzors

ssgvzors1#

在12c中,当前的子程序名称只是:

  1. utl_call_stack.subprogram(1)(2);

目前的套餐也可以从

  1. utl_call_stack.subprogram(1)(1);

但通常更容易仅使用$$plsql_unit。您也可以获得限定名(package.procedure):

  1. utl_call_stack.concatenate_subprogram(utl_call_stack.subprogram(1));

然而,我想不出任何情况下,一个过程或函数(或对象方法)会想要自己的名字。此功能在日志记录过程中最有用,在这种情况下 '谁叫我?' 代码应该在日志记录器中,而不是在调用它的每个事物中重复。因此,我强烈建议避免任何 '我是谁?' 程序中的逻辑。相反,将类似这样的东西放在日志记录器中(需要12个。1或更高版本):

  1. create or replace procedure logdemo
  2. as
  3. -- This is a package name, standalone function name, standalone procedure name,
  4. -- or "__anonymous_block".
  5. k_calling_subprogram1 varchar2(128);
  6. -- This is a package procedure name or package function name, and it is NULL if
  7. -- the parent is a standalone function, standalone procedure, or anonymous block.
  8. k_calling_subprogram2 varchar2(128);
  9. begin
  10. k_calling_subprogram1 := utl_call_stack.subprogram(2)(1);
  11. begin
  12. k_calling_subprogram2 := utl_call_stack.subprogram(2)(2);
  13. exception when subscript_beyond_count then
  14. k_calling_subprogram2 := null;
  15. end;
  16. dbms_output.put_line
  17. ( $$plsql_unit ||
  18. ' called from subprogram1 '||k_calling_subprogram1
  19. ||', subprogram2 '||k_calling_subprogram2 );
  20. end logdemo;
  21. /

不幸的是,在11g中它有点复杂,因为你必须解析dbms_utility.format_call_stack,并且因为这只给你包名和行号(在换行符分隔的文本字符串中),然后你必须查询all_source来找到子程序名。
我可以张贴一些11g代码,如果你澄清它的用途。在我的11g logger中,我发现根据sqlcode等捕获dbms_utility.format_error_backtracedbms_utility.format_call_stack很有用,所以有一堆特定于日志记录的逻辑,如果你只是想捕获当前过程名,你可能不需要这些逻辑。

展开查看全部
bq9c1y66

bq9c1y662#

如果它是一个独立的程序(i.即不是包内的那个),你会很容易得到答案:

  1. SQL> create or replace procedure p_test is
  2. 2 begin
  3. 3 dbms_output.put_line('I am ' || $$plsql_unit);
  4. 4 null;
  5. 5 end;
  6. 6 /
  7. Procedure created.
  8. SQL> exec p_test
  9. I am P_TEST
  10. PL/SQL procedure successfully completed.
  11. SQL>

对于包来说,事情不再那么简单了。上面的选项(使用$$plsql_unit)返回的是包体名称,而不是过程名称:

  1. SQL> create or replace package pkg_test as
  2. 2 procedure p_test_in_pkg;
  3. 3 end;
  4. 4 /
  5. Package created.
  6. SQL> create or replace package body pkg_test as
  7. 2 procedure p_test_in_pkg is
  8. 3 begin
  9. 4 dbms_output.put_line('Packaged procedure whose name is ' || $$plsql_unit);
  10. 5 null;
  11. 6 end;
  12. 7 end;
  13. 8 /
  14. Package body created.
  15. SQL> exec pkg_test.p_test_in_pkg;
  16. Packaged procedure whose name is PKG_TEST --> should have been "p_test_in_pkg"
  17. PL/SQL procedure successfully completed.

以下功能似乎正在工作。作者是 garbuya,来源是OTN论坛的讨论Efficient WHO_AM_I and WHO_CALLED_ME讨论(2010年)。

  1. create or replace
  2. FUNCTION FN_WHO_AM_I ( p_lvl NUMBER DEFAULT 0) RETURN VARCHAR2
  3. IS
  4. /***********************************************************************************************
  5. FN_WHO_AM_I returns the full ORACLE name of your object including schema and package names
  6. --
  7. FN_WHO_AM_I(0) - returns the name of your object
  8. FN_WHO_AM_I(1) - returns the name of calling object
  9. FN_WHO_AM_I(2) - returns the name of object, who called calling object
  10. etc., etc., etc.... Up to to he highest level
  11. -------------------------------------------------------------------------------------------------
  12. Copyrigth GARBUYA 2010
  13. *************************************************************************************************/
  14. TYPE str_varr_t IS VARRAY(2) OF CHAR(1);
  15. TYPE str_table_t IS TABLE OF VARCHAR2(256);
  16. TYPE num_table_t IS TABLE OF NUMBER;
  17. v_stack VARCHAR2(2048) DEFAULT UPPER(dbms_utility.format_call_stack);
  18. v_tmp_1 VARCHAR2(1024);
  19. v_tmp_2 VARCHAR2(1024);
  20. v_pkg_name VARCHAR2(32);
  21. v_obj_type VARCHAR2(32);
  22. v_owner VARCHAR2(32);
  23. v_idx NUMBER := 0;
  24. v_pos1 NUMBER := 0;
  25. v_pos2 NUMBER := 0;
  26. v_line_nbr NUMBER := 0;
  27. v_blk_cnt NUMBER := 0;
  28. v_str_len NUMBER := 0;
  29. v_bgn_cnt NUMBER := 0;
  30. v_end_cnt NUMBER := 0;
  31. it_is_comment BOOLEAN := FALSE;
  32. it_is_literal BOOLEAN := FALSE;
  33. v_literal_arr str_varr_t := str_varr_t ('''', '"');
  34. v_blk_bgn_tbl str_table_t := str_table_t (' IF ' , ' LOOP ' , ' CASE ', ' BEGIN ');
  35. v_tbl str_table_t := str_table_t();
  36. v_blk_bgn_len_tbl num_table_t := num_table_t();
  37. BEGIN
  38. v_stack := SUBSTR(v_stack,INSTR(v_stack,CHR(10),INSTR(v_stack,'FN_WHO_AM_I'))+1)||'ORACLE'; -- skip myself
  39. FOR v_pos2 in 1 .. p_lvl LOOP -- advance to the input level
  40. v_pos1 := INSTR(v_stack, CHR(10));
  41. v_stack := SUBSTR(v_stack, INSTR(v_stack, CHR(10)) + 1);
  42. END LOOP;
  43. v_pos1 := INSTR(v_stack, CHR(10));
  44. IF v_pos1 = 0 THEN
  45. RETURN (v_stack);
  46. END IF;
  47. v_stack := SUBSTR(v_stack, 1, v_pos1 - 1); -- get only current level
  48. v_stack := TRIM(SUBSTR(v_stack, instr(v_stack, ' '))); -- cut object handle
  49. v_line_nbr := TO_NUMBER(SUBSTR(v_stack, 1, instr(v_stack, ' ') - 1)); -- get line number
  50. v_stack := TRIM(SUBSTR(v_stack, instr(v_stack, ' '))); -- cut line number
  51. v_pos1 := INSTR(v_stack, ' BODY');
  52. IF v_pos1 = 0 THEN
  53. RETURN (v_stack);
  54. END IF;
  55. v_pos1 := INSTR(v_stack, ' ', v_pos1 + 2); -- find end of object type
  56. v_obj_type := SUBSTR(v_stack, 1, v_pos1 - 1); -- get object type
  57. v_stack := TRIM(SUBSTR(v_stack, v_pos1 + 1)); -- get package name
  58. v_pos1 := INSTR(v_stack, '.');
  59. v_owner := SUBSTR(v_stack, 1, v_pos1 - 1); -- get owner
  60. v_pkg_name := SUBSTR(v_stack, v_pos1 + 1); -- get package name
  61. v_blk_cnt := 0;
  62. it_is_literal := FALSE;
  63. --
  64. FOR v_idx in v_blk_bgn_tbl.FIRST .. v_blk_bgn_tbl.LAST
  65. LOOP
  66. v_blk_bgn_len_tbl.EXTEND(1);
  67. v_blk_bgn_len_tbl (v_blk_bgn_len_tbl.last) := LENGTH(v_blk_bgn_tbl(v_idx));
  68. END LOOP;
  69. --
  70. FOR src
  71. IN ( SELECT ' '||REPLACE(TRANSLATE(UPPER(text), ';('||CHR(10), ' '),'''''',' ') ||' ' text
  72. FROM all_source
  73. where owner = v_owner
  74. and name = v_pkg_name
  75. and type = v_obj_type
  76. and line < v_line_nbr
  77. ORDER BY line
  78. )
  79. LOOP
  80. v_stack := src.text;
  81. IF it_is_comment THEN
  82. v_pos1 := INSTR (v_stack, '*/');
  83. IF v_pos1 > 0 THEN
  84. v_stack := SUBSTR (v_stack, v_pos1 + 2);
  85. it_is_comment := FALSE;
  86. ELSE
  87. v_stack := ' ';
  88. END IF;
  89. END IF;
  90. --
  91. IF v_stack != ' ' THEN
  92. --
  93. v_pos1 := INSTR (v_stack, '/*');
  94. WHILE v_pos1 > 0 LOOP
  95. v_tmp_1 := SUBSTR (v_stack, 1, v_pos1 - 1);
  96. v_pos2 := INSTR (v_stack, '*/');
  97. IF v_pos2 > 0 THEN
  98. v_tmp_2 := SUBSTR (v_stack, v_pos2 + 2);
  99. v_stack := v_tmp_1||v_tmp_2;
  100. ELSE
  101. v_stack := v_tmp_1;
  102. it_is_comment := TRUE;
  103. END IF;
  104. v_pos1 := INSTR (v_stack, '/*');
  105. END LOOP;
  106. --
  107. IF v_stack != ' ' THEN
  108. v_pos1 := INSTR (v_stack, '--');
  109. IF v_pos1 > 0 THEN
  110. v_stack := SUBSTR (v_stack, 1, v_pos1 - 1);
  111. END IF;
  112. --
  113. IF v_stack != ' ' THEN
  114. FOR v_idx in v_literal_arr.FIRST .. v_literal_arr.LAST
  115. LOOP
  116. v_pos1 := INSTR (v_stack, v_literal_arr (v_idx) );
  117. WHILE v_pos1 > 0 LOOP
  118. v_pos2 := INSTR (v_stack, v_literal_arr (v_idx), v_pos1 + 1);
  119. IF v_pos2 > 0 THEN
  120. v_tmp_1 := SUBSTR (v_stack, 1, v_pos1 - 1);
  121. v_tmp_2 := SUBSTR (v_stack, v_pos2 + 1);
  122. v_stack := v_tmp_1||v_tmp_2;
  123. ELSE
  124. IF it_is_literal THEN
  125. v_stack := SUBSTR (v_stack, v_pos1 + 1);
  126. it_is_literal := FALSE;
  127. ELSE
  128. v_stack := SUBSTR (v_stack, 1, v_pos1 - 1);
  129. it_is_literal := TRUE;
  130. END IF;
  131. END IF;
  132. v_pos1 := INSTR (v_stack, v_literal_arr (v_idx) );
  133. END LOOP;
  134. END LOOP;
  135. --
  136. IF v_stack != ' ' THEN
  137. WHILE INSTR (v_stack, ' ') > 0
  138. LOOP
  139. v_stack := REPLACE(v_stack, ' ', ' ');
  140. END LOOP;
  141. v_stack := REPLACE(v_stack, ' END IF ', ' END ');
  142. v_stack := REPLACE(v_stack, ' END LOOP ', ' END ');
  143. --
  144. IF v_stack != ' ' THEN
  145. v_stack := ' '||v_stack;
  146. v_pos1 := INSTR(v_stack, ' FUNCTION ') + INSTR(v_stack, ' PROCEDURE ');
  147. IF v_pos1 > 0 THEN
  148. v_obj_type := TRIM(SUBSTR(v_stack, v_pos1 + 1, 9)); -- get object type
  149. v_stack := TRIM(SUBSTR(v_stack, v_pos1 + 10))||' '; -- cut object type
  150. v_stack := SUBSTR(v_stack, 1, INSTR(v_stack, ' ') - 1 ); -- get object name
  151. v_tbl.EXTEND(1);
  152. v_tbl (v_tbl.last) := v_obj_type||' '||v_owner||'.'||v_pkg_name||'.'||v_stack;
  153. END IF;
  154. --
  155. v_pos1 := 0;
  156. v_pos2 := 0;
  157. v_tmp_1 := v_stack;
  158. v_tmp_2 := v_stack;
  159. FOR v_idx in v_blk_bgn_tbl.FIRST .. v_blk_bgn_tbl.LAST
  160. LOOP
  161. v_str_len := NVL(LENGTH(v_tmp_1),0);
  162. v_tmp_1 := REPLACE(v_tmp_1,v_blk_bgn_tbl(v_idx), NULL);
  163. v_bgn_cnt := NVL(LENGTH(v_tmp_1), 0);
  164. v_pos1 := v_pos1 + (v_str_len - v_bgn_cnt)/v_blk_bgn_len_tbl(v_idx);
  165. v_str_len := NVL(LENGTH(v_tmp_2),0);
  166. v_tmp_2 := REPLACE(v_tmp_2,' END ', NULL);
  167. v_end_cnt := NVL(LENGTH(v_tmp_2), 0);
  168. v_pos2 := v_pos2 + (v_str_len - v_end_cnt)/5; --- 5 is the length(' END ')
  169. END LOOP;
  170. IF v_pos1 > v_pos2 THEN
  171. v_blk_cnt := v_blk_cnt + 1;
  172. ELSIF v_pos1 < v_pos2 THEN
  173. v_blk_cnt := v_blk_cnt - 1;
  174. IF v_blk_cnt = 0 AND v_tbl.COUNT > 0 THEN
  175. v_tbl.DELETE(v_tbl.last);
  176. END IF;
  177. END IF;
  178. END IF;
  179. END IF;
  180. END IF;
  181. END IF;
  182. END IF;
  183. END LOOP;
  184. RETURN CASE v_tbl.COUNT WHEN 0 THEN 'UNKNOWN' ELSE v_tbl(v_tbl.LAST) END;
  185. END;
  186. /

测试:

  1. SQL> create or replace package body pkg_test as
  2. 2 procedure p_test_in_pkg is
  3. 3 begin
  4. 4 dbms_output.put_line('Packaged procedure, using $$plsql_unit = ' || $$plsql_unit);
  5. 5 dbms_output.put_line('FN_WHO_AM_I = ' || fn_who_am_i);
  6. 6 null;
  7. 7 end;
  8. 8 end;
  9. 9 /
  10. Package body created.
  11. SQL> exec pkg_test.p_test_in_pkg;
  12. Packaged procedure, using $$plsql_unit = PKG_TEST --> this one is wrong (package body name) ...
  13. FN_WHO_AM_I = PROCEDURE SCOTT.PKG_TEST.P_TEST_IN_PKG --> ... but this one is OK
  14. PL/SQL procedure successfully completed.
  15. SQL>
展开查看全部
jgovgodb

jgovgodb3#

一种方法使用从这里借用的想法:http://www.orafaq.com/forum/t/173023/

注意:这只适用于Oracle 12c。对于11g,它只给出了包名称。

创建一个名为show_caller的过程。这使用了OWA_UTIL.WHO_CALLED_ME过程。

  1. create or replace procedure show_caller
  2. as
  3. l_owner varchar2(200);
  4. l_name varchar2(200);
  5. l_lineno number;
  6. l_caller varchar2(200);
  7. begin
  8. OWA_UTIL.WHO_CALLED_ME (l_owner, l_name,l_lineno,l_caller);
  9. dbms_output.put_line('Inside '||l_name);
  10. end;
  11. /

现在,你可以把你的包写成:

  1. CREATE OR replace PACKAGE test_pkg
  2. AS
  3. PROCEDURE proc1;
  4. END test_pkg;
  5. /
  6. CREATE OR replace PACKAGE BODY test_pkg
  7. AS
  8. PROCEDURE Proc1
  9. AS
  10. BEGIN
  11. show_caller; -- proc1 calls show_caller
  12. END proc1;
  13. END test_pkg;
  14. /

处决

  1. SET SERVEROUTPUT ON
  2. BEGIN
  3. Test_pkg.Proc1;
  4. END;
  5. /
  6. Inside TEST_PKG.PROC1

请注意,这将打印过程的名称。如果要将其作为变量使用,则将l_name(如果需要,还可以与其他变量沿着)作为OUT变量从show_caller传递
Live SQL Demo(需要免费OTN帐户)
另一种选择是在过程中使用OWA_UTIL.GET_PROCEDURE函数:但在这种情况下似乎不适合我我很乐意从Maven那里了解更多。

展开查看全部
suzh9iv8

suzh9iv84#

我的快速样本:

  1. create or replace package body MyPackage as
  2. procedure PrintMethodName is
  3. ThisMethod#FullName varchar2(128) := regexp_substr(
  4. dbms_utility.format_call_stack,
  5. 'package\s+body\s+([^[:space:]]+)',
  6. 1,1,'i',1); -- schema.package.method
  7. ThisMethod#CurrentSchemaName varchar2(128) := regexp_substr(
  8. regexp_substr(
  9. dbms_utility.format_call_stack,
  10. 'package\s+body\s+([^[:space:]]+)',
  11. 1,1,'i',1),
  12. '[^.]+[.][^.]+$'); -- package.method
  13. ThisMethod#MethodName varchar2(128) := regexp_substr(
  14. regexp_substr(
  15. dbms_utility.format_call_stack,
  16. 'package\s+body\s+([^[:space:]]+)',
  17. 1,1,'i',1),
  18. '[^.]+$'); -- method
  19. begin
  20. dbms_output.put_line(dbms_utility.format_call_stack);
  21. dbms_output.put_line(ThisMethod#FullName);
  22. dbms_output.put_line(ThisMethod#CurrentSchemaName);
  23. dbms_output.put_line(ThisMethod#MethodName);
  24. end;
  25. end;
  26. /
展开查看全部

相关问题