在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。如何确定调用是否发生在主功能块内?
答案 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中由'->'
分隔的调用层次结构