我需要找到函数/过程(在包体内定义)和它们使用的表之间的依赖关系。
我已经尝试过
all_dependencies
,但它仅适用于包级别,而不适用于内部函数/过程级别。
是否有可能使用例如找到此依赖项all_source
?
预先感谢您的帮助。
不可能找到程序(在包中)和表之间的依赖关系。
有多种工具可以检查依赖性。 正如您已经发现的,
*_DEPENDENCIES
仅跟踪每个包级别的对象依赖关系。 有一个简洁的工具 PL/Scope 可以跟踪包各部分之间的依赖关系。 但它确实不跟踪所有表引用。
理论上你可以使用
*_SOURCE
。 实际上,除非您的代码使用一组有限的功能,否则这是不可能的。 对于任何中等复杂的代码,请忘记使用字符串函数或正则表达式来解析代码。 不幸的是,似乎没有任何既可编程又能够准确解析复杂代码的 PL/SQL 解析器。
说“这是不可能的”并不是一个很好的答案。 但在这种情况下,它可能会节省你很多时间。 这是很容易陷入死胡同并浪费大量精力的任务之一。
如果需要,您可以使用此过程
首先激活 PL/Scope 并重新编译您的 PL/SQL 包
-- activate PL/Scope
ALTER SESSION SET plscope_settings='identifiers:all';
-- this will feed the data in *_identifiers and *_statements views
ALTER PACKAGE MY_PACKAGE COMPILE;
-- deactivate PL/Scope
ALTER SESSION SET plscope_settings='identifiers:none';
然后您可以使用此查询:
-- CREATE OR REPLACE VIEW tables_usage_in_plsql AS
WITH stmt_upd_ins_del as (
select /*+MATERIALIZE*/ s.object_name, s.object_type, s.type, s.usage_id, s.line
from user_statements s
where s.object_type = 'PACKAGE BODY'
and s.type in ('UPDATE','DELETE','INSERT')
group by s.object_name, s.object_type, s.type, s.usage_id, s.line
)
select s.object_name, s.object_type, s.type as stmt_type, i.usage_context_id, s.line
, count(1) as nb_objs_in_dml
, min(i.name) keep(dense_rank first order by i.line, i.col) as dml_object
, min(i.type) keep(dense_rank first order by i.line, i.col) as typ_obj_dml
, min(i.usage_id) keep(dense_rank first order by i.line, i.col) as uid_obj_dml
from user_identifiers i
inner join stmt_upd_ins_del s
on i.object_type = s.object_type and i.object_name = s.object_name and i.usage_context_id = s.usage_id
where i.object_type = 'PACKAGE BODY' -- NB: filtering again here to help the optimizer
and i.object_name = 'MY_PACKAGE' -- remove this line if you want to process several packages
and i.type in ('VIEW','TABLE')
group by s.object_name, s.object_type, s.type, i.usage_context_id, s.line
UNION ALL
select i.object_name, i.object_type, 'SELECT' as stmt_type, i.usage_context_id, i.line
, count(1) over (partition by usage_context_id) as nb_objs_in_dml
, i.name as dml_object, i.type as typ_obj_dml, usage_id as uid_obj_dml
from user_identifiers i
where i.object_type = 'PACKAGE BODY'
and i.object_name = 'MY_PACKAGE' -- remove this line if you want to process several packages
and i.type in ('VIEW','TABLE');
我在查询中做了几个假设,否则事情会变得非常复杂:
您还可以根据之前的查询创建一个视图,然后使用它来获取每个 PL/SQL 包的所有 DML 语句,例如:
select object_type, object_name, objet_dml, typ_obj_dml, count(1) as tot_usages
,sum(CASE WHEN type = 'INSERT' then 1 else 0 end) as nb_inserts
,sum(CASE WHEN type = 'UPDATE' then 1 else 0 end) as nb_updates
,sum(CASE WHEN type = 'DELETE' then 1 else 0 end) as nb_deletes
,sum(CASE WHEN type = 'SELECT' then 1 else 0 end) as nb_selects
from tables_usage_in_plsql
group by object_type, object_name, objet_dml, typ_obj_dml
order by 1,2,3,4;
希望这有帮助