如何在oracle中获取调用者对象的名称

时间:2019-04-09 10:01:25

标签: oracle plsql oracle11g callstack

在Oracle中,将调用者对象包装在包装中时,正确获取其名称很复杂。这是我尝试实现的目标:

CREATE OR REPLACE function GET_MY_NAME return varchar2 is
  v_owner      varchar2(50);
  v_name       varchar2(50);
  v_lineno     number      ;
  v_caller_t   varchar2(50);
begin
  -- let's determine the object
  owa_util.who_called_me(
    v_owner
  , v_name
  , v_lineno
  , v_caller_t
  );
  dbms_output.put_line(v_caller_t || ' ' || v_owner || '.' || v_name || ' at ' || v_lineno);
  with s as (
    select s.*
         , max(line - 1) over (partition by name order by line rows between 1 following and 1 following) to_line
         , regexp_substr(s.text, '\w+', 1, 2) func_name
      from all_source s
     where s.type  = v_caller_t
       and s.owner = v_owner
       and s.name  = v_name
       and regexp_like(s.text, 'procedure|function')
  )
  select max(nvl(s.func_name, v_name ))
       , max(nvl(s.name     , v_owner))
    into v_name, v_owner
    from s
   where v_lineno between s.line and nvl(s.to_line, 9999999);  
  return v_owner || '.' || v_name;
end;

该想法是确定每个内部对象的源内的线的位置并采取相应的对象。这对于软件包很好用,但是对于功能和过程,它无法确定是否从主块中调用了它。这是一个小演示:

create or replace function check_my_name return varchar2 is
  function sub_check_my_name return varchar2 is
  begin
    return get_my_name;
  end;
begin
  dbms_output.put_line(sub_check_my_name);
  return get_my_name;
end;
/

您可以看到sub_check_my_name有效,但是直接调用get_my_name也会返回sub_check_my_name。如何确定调用是否发生在主功能块内?

1 个答案:

答案 0 :(得分:0)

我做了这样简单的事情,

声明如下变量,

call_stack VARCHAR2(3000) := '';

现在使用下面的方法获取通话级别,

FOR j IN REVERSE 1..utl_call_stack.dynamic_depth() LOOP
        call_stack := CASE
            WHEN call_stack IS NOT NULL THEN
                call_stack || '->'
                      END
                      || nvl(utl_call_stack.concatenate_subprogram(utl_call_stack.subprogram(j)), '');
    END LOOP;

dbms_output.put_line(call_stack);

这给出了call_stack中由'->'分隔的调用层次结构