2017-06-16 38 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