SQL查询 - 包x的公共和私有对象

时间:2017-06-16 12:53:04

标签: sql oracle

我想构建一个列出PL / SQL包的可用对象(过程和函数)的查询,以及另一个列privacy_level,它显示该对象是否存在于body和spec(是公共的)中,或者只在身体内(是私人的)。

浏览一下后,我才发现这个查询(不返回任何行)

select name, 
       type,
       decode(usage,'DECLARATION', 'body only', 'DEFINITION', 'spec and body', usage) defined_on,
       line body_line
  from all_identifiers ui
  where type in ('PROCEDURE', 'FUNCTION')
  and usage_context_id = (select usage_id
    from user_identifiers
      where object_name = ui.object_name
        and object_type = ui.object_type
        and usage_context_id = 0)
  --and object_name = 'PACKAGE_NAME'
  --and object_type = 'PACKAGE BODY'
  order by name;

提前谢谢。

1 个答案:

答案 0 :(得分:1)

您的查询针对all_identifiersPLSCOPE_SETTINGSthe PL/Scope tool的一部分。该系统视图仅显示使用适当设置编译的对象的数据:

  

默认情况下,PL / Scope不会收集PL / SQL源程序中标识符的数据。要让PL / Scope收集PL / SQL源程序中所有标识符的数据,包括包体中的标识符,请将PL / SQL编译参数'IDENTIFIERS:ALL'设置为create package p42 as procedure public_proc; function public_func return number; end p42; / create package body p42 as procedure public_proc is begin null; end public_proc; function public_func return number is begin return 42; end public_func; procedure private_proc is begin null; end private_proc; function private_func return number is begin return 42; end private_func; end p42; /

如果我使用默认设置创建包含私有和公共子程序的包:

select name, 
...
  order by name;

no rows selected

然后您使用查询找不到任何内容:

PLSCOPE_SETTINGS

如果我在创建之前设置了alter session set plscope_settings = 'IDENTIFIERS:ALL'; Session altered. alter package p42 compile; Package P42 altered. ,那么它们就会显示出来;假设您不想完全重新创建更改设置后可以重新编译包的所有内容:

NAME                           TYPE               DEFINED_ON     BODY_LINE
------------------------------ ------------------ ------------- ----------
PRIVATE_FUNC                   FUNCTION           body only             17
PRIVATE_PROC                   PROCEDURE          body only             12
PUBLIC_FUNC                    FUNCTION           body only              3
PUBLIC_FUNC                    FUNCTION           spec and body          7
PUBLIC_PROC                    PROCEDURE          body only              2
PUBLIC_PROC                    PROCEDURE          spec and body          2

6 rows selected. 

现在您的查询得到:

select object_name, type, name,
  case min(object_type) when 'PACKAGE BODY' then 'PRIVATE' else 'PUBLIC' end as privacy_level
from user_identifiers
where object_type in ('PACKAGE', 'PACKAGE BODY')
and type in ('FUNCTION', 'PROCEDURE')
group by object_name, type, name
order by object_name, name;

OBJECT_NAME     TYPE               NAME            PRIVACY
--------------- ------------------ --------------- -------
P42             FUNCTION           PRIVATE_FUNC    PRIVATE
P42             PROCEDURE          PRIVATE_PROC    PRIVATE
P42             FUNCTION           PUBLIC_FUNC     PUBLIC 
P42             PROCEDURE          PUBLIC_PROC     PUBLIC 

这样的事情可能更接近于你所说的你想要实现的目标,使用私有子程序仅作为正文的一部分出现在表中的事实:

exec dbms_utility.compile_schema(user);

如果要查找所有对象的此信息,可以单独重新编译它们,也可以重新编译整个模式:

All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.

但要注意,如果你的任何包有状态,那么当他们调用它们时,现有的会话可能会出错(所以你可能希望在停机期间这样做),并且如果有人编译任何东西而没有明确地改变他们的会话那么那些对象就不会由您查询显示(除非您在数据库级别设置它,这可能是太多的开销)。

相关问题