2017-06-16 32 views
0

我想构建一个查询,列出PL/SQL包的可用对象(过程和函数),并附加一列privacy_level,用于显示该对象是否存在于身体和规范(是公开的),或仅在身体(是私人的)。SQL查询 - 包x的公共和私有对象x

浏览一点后,我才发现这个查询(其中不返回行)

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; 

预先感谢您。

+2

这似乎工作(不能添加非答案演示)。在编译软件包之前,你是否已经改变了会话集plscope_settings ='IDENTIFIERS:ALL';'? –

回答

1

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

默认情况下,PL/Scope不收集PL/SQL源程序中标识符的数据。要使PL/Scope收集PL/SQL源程序中所有标识符的数据(包括包体中的标识符),请将PL/SQL编译参数PLSCOPE_SETTINGS设置为'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 

如果你想找到这个信息,供各位c都对象一个单独重新编译或重新编译整个架构:

exec dbms_utility.compile_schema(user); 

但要注意,如果有您的包裹有状态,当他们打电话给他们,然后现有会话可能出错(所以你可能想这样做,停机期间) ,如果任何人在没有明确改变会话的情况下编译任何东西,那么你的查询就不会显示这些对象(除非你在数据库级别设置它,这可能会造成太多开销)。

+0

你知道在运行时是否有任何开销来编译'IDENTIFIERS:ALL'?我不担心运行时间可能更长的编译时间。 – BriteSponge

+0

@BriteSponge - 不是我所知道的,似乎不太可能。在编译时甚至可能没有大量的开销,但是对于大型软件包来说可能会很明显,并且可能会在开发周期中累加起来 - 只需在使用alter system之前考虑一下。存在[一些存储成本](http://docs.oracle.com/cd/B28359_01/appdev.111/b28424/adfns_plscope.htm#BABDHFIF),但可能并不重要。 –

+1

我会调查我认为的PLScope内容,目的是提议我们在数据库级别打开它。听起来像它有可能在几乎没有成本的情况下有用。 – BriteSponge