您可以在包with PL/Scope 中获取对过程的调用,以:
alter session set plscope_settings = 'IDENTIFIERS:ALL';
如果你随后重新编译你的包,这里根据你的描述使用一个简单的大纲:
create or replace package p42 as
procedure a;
procedure b;
procedure c;
procedure d;
function f return number;
end p42;
/
create or replace package body p42 as
procedure a is
begin
b;
c;
end a;
procedure b is
n number;
begin
n := f;
end b;
procedure c is
n number;
begin
n := f;
end c;
procedure d is
begin
null;
end d;
function f return number is
begin
return 42;
end f;
end p42;
/
然后您可以在user_identifiers 视图中看到各种引用。使用文档中的示例获取大纲:
WITH v AS (
SELECT Line,
Col,
INITCAP(NAME) Name,
LOWER(TYPE) Type,
LOWER(USAGE) Usage,
USAGE_ID,
USAGE_CONTEXT_ID
FROM USER_IDENTIFIERS
WHERE Object_Name = 'P42'
AND Object_Type = 'PACKAGE BODY'
)
SELECT RPAD(LPAD(' ', 2*(Level-1)) ||
Name, 20, '.')||' '||
RPAD(Type, 20)||
RPAD(Usage, 20)
IDENTIFIER_USAGE_CONTEXTS
FROM v
START WITH USAGE_CONTEXT_ID = 0
CONNECT BY PRIOR USAGE_ID = USAGE_CONTEXT_ID
ORDER SIBLINGS BY Line, Col
/
IDENTIFIER_USAGE_CONTEXTS
-------------------------------------------------------------
P42................. package definition
A................. procedure definition
B............... procedure call
C............... procedure call
B................. procedure definition
N............... variable declaration
Number........ number datatype reference
N............... variable assignment
F............. function call
C................. procedure definition
N............... variable declaration
Number........ number datatype reference
N............... variable assignment
F............. function call
D................. procedure definition
F................. function definition
Number.......... number datatype reference
要获得更接近您想要的内容,您仍然需要一个分层查询来查找调用另一个的每个过程/函数的名称,因为您不感兴趣(例如)分配步骤,只是那些发生的位置。
作为一个起点,你可以这样做:
select *
from (
select name, type, connect_by_root(name) as root_name,
connect_by_root(type) as root_type, connect_by_isleaf as isleaf
from user_identifiers
start with object_type = 'PACKAGE BODY'
and object_name = 'P42'
and type in ('FUNCTION', 'PROCEDURE')
and usage = 'DEFINITION'
connect by object_type = prior object_type
and object_name = prior object_name
and usage_context_id = prior usage_id
)
where type in ('FUNCTION', 'PROCEDURE');
NAME TYPE ROOT_NAME ROOT_TYPE ISLEAF
---- ------------------ --------- --------- ----------
A PROCEDURE A PROCEDURE 0
B PROCEDURE A PROCEDURE 1
C PROCEDURE A PROCEDURE 1
B PROCEDURE B PROCEDURE 0
F FUNCTION B PROCEDURE 1
C PROCEDURE C PROCEDURE 0
F FUNCTION C PROCEDURE 1
D PROCEDURE D PROCEDURE 1
F FUNCTION F FUNCTION 0
然后过滤叶子节点并合并调用者:
select root_name, root_type,
listagg(case when name = root_name then null else name end, ', ')
within group (order by name) as callers
from (
select name, type, connect_by_root(name) as root_name,
connect_by_root(type) as root_type, connect_by_isleaf as isleaf
from user_identifiers
start with object_type = 'PACKAGE BODY'
and object_name = 'P42'
and type in ('FUNCTION', 'PROCEDURE')
and usage = 'DEFINITION'
connect by object_type = prior object_type
and object_name = prior object_name
and usage_context_id = prior usage_id
)
where type in ('FUNCTION', 'PROCEDURE')
and isleaf = 1
group by root_name, root_type;
ROOT_NAME ROOT_TYPE CALLERS
--------- --------- --------------------
A PROCEDURE B, C
B PROCEDURE F
C PROCEDURE F
D PROCEDURE
但这并没有显示F;你可以添加一个外部连接来获得它:
with ui as (
select * from user_identifiers
where object_type = 'PACKAGE BODY'
and object_name = 'P42'
),
calls as (
select object_type, object_name, name, type, signature,
connect_by_root(name) as root_name,
connect_by_root(type) as root_type,
connect_by_root(signature) as root_signature,
connect_by_isleaf as isleaf
from ui
start with type in ('FUNCTION', 'PROCEDURE')
and usage = 'DEFINITION'
connect by usage_context_id = prior usage_id
and prior usage != 'CALL'
)
select ui.name, ui.type,
listagg(case when c.name = c.root_name then null else c.name end, ', ')
within group (order by c.name) as callers
from ui
left join calls c on c.object_type = ui.object_type
and c.object_name = ui.object_name
and c.root_type = ui.type
and c.root_name = ui.name
and c.root_signature = ui.signature
and c.type in ('FUNCTION', 'PROCEDURE')
and c.isleaf = 1
where ui.type in ('FUNCTION', 'PROCEDURE')
and ui.usage = 'DEFINITION'
group by ui.name, ui.type;
NAME TYPE CALLERS
---- ------------------ --------------------
A PROCEDURE B, C
B PROCEDURE F
C PROCEDURE F
D PROCEDURE
F FUNCTION
我很确定可以简化...
获取主/从/独立标志有点棘手;您需要确定其中每一个的含义(例如 main 有呼叫出去但没有呼叫进来;独立没有呼入或呼出;从属其他一切)可能还有进一步的加入来解决问题。
因此,这是一个起点,它可以为您提供一些信息,并希望指出要探索的内容,以便以您需要的格式获取您需要的所有信息。