【问题标题】:SQL query - public and private objects of package xSQL 查询 - 包 x 的公共和私有对象
【发布时间】:2017-06-16 21:42:46
【问题描述】:

我想构建一个查询,列出 PL/SQL 包的可用对象(过程和函数),并带有一个附加列,privacy_level,显示该对象是否同时存在于正文和规范中(是公共的),或者仅在正文中(私有)。

浏览了一下,我只找到了这个查询(没有返回任何行)

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;

提前谢谢你。

【问题讨论】:

  • 这似乎有效(如果不添加非答案就无法演示)。你在编译你的包之前做了alter session set plscope_settings = 'IDENTIFIERS:ALL';吗?

标签: sql oracle


【解决方案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 

如果您想找到所有对象的这些信息,您可以单独重新编译它们,或者重新编译整个架构:

exec dbms_utility.compile_schema(user);

但请注意,如果您的任何包具有状态,那么现有会话在调用它们时可能会出错(因此您可能希望在停机期间这样做),并且如果有人编译任何东西而不显式更改其会话,那么这些对象将不会由您的查询显示(除非您在数据库级别设置它,这可能开销太大)。

【讨论】:

  • 您知道在运行时使用 'IDENTIFIERS:ALL' 编译是否有任何开销?我不担心编译时间可能更长,只是运行时间。
  • @BriteSponge - 我不知道,而且似乎不太可能。在编译时甚至可能没有大量的开销,但对于大型包来说可能很明显,并且可能会在开发周期中累加 - 只是在启用 alter system 之前需要考虑的事情。还有some storage cost,但同样可能并不重要。
  • 我将研究我认为的 PLScope 东西,以建议我们在数据库级别打开它。听起来它有可能以很少甚至免费的方式发挥作用。
猜你喜欢
  • 2015-12-27
  • 2012-05-14
  • 2017-10-11
  • 2011-07-29
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-28
相关资源
最近更新 更多