有啥方法可以确定包在 Oracle 中是不是有状态?

Posted

技术标签:

【中文标题】有啥方法可以确定包在 Oracle 中是不是有状态?【英文标题】:Is there any way to determine if a package has state in Oracle?有什么方法可以确定包在 Oracle 中是否有状态? 【发布时间】:2012-06-18 01:17:19 【问题描述】:

Oracle 中有没有办法确定一个包是有状态还是无状态?我不知道包含该信息的数据字典中的任何视图。

“ORA-04068:包字符串的现有状态已被丢弃”错误相当烦人。它可以通过从包中删除包变量来消除。 11g 引入了一个特性,一个包含所有编译时常量的变量的包将被视为无状态。

我可以有两个会话,在一个会话中编译包并在另一个中调用它,看看它是否引发异常,但这需要调用包中的一个过程,这可能是不可取的。

【问题讨论】:

在我回答之前,你能解释一下你为什么想知道吗?不要试图成为一个痛苦,只是试图了解你到底想做什么。为什么知道包是否有状态对您很重要?此外,您是否只是想知道一个包是否有状态,因此是否可能在某个时候遇到 ORA-4068?或者,对于有状态的包,您是否有兴趣了解包的当前状态是有效、无效还是未初始化? 有状态的包可能很烦人,因为如果在会话打开时进行更改,可能会导致用户出错。我有一个包有这个问题,我正在重构它以使其成为无状态并遇到一些麻烦(这将是未来 SO 问题的主题),所以有一种简单的方法来判断包是无状态的还是不是。此外,数据库中的哪些其他包是有状态的,也可能导致此问题。 【参考方案1】:

听起来你想要的是能够列出所有可能有状态的包。

您正在寻找的只是具有任何全局变量或常量的包。对于单个包装,这通过检查非常简单。但是,要查看模式中的所有包,您可以使用 PL/Scope:

首先,以架构所有者身份登录,在会话中打开 PL/Scope:

alter session set plscope_settings='IDENTIFIERS:ALL';

然后,重新编译所有包体。

然后,运行此查询以查找在包级别声明的所有变量和常量:

select object_name AS package,
       type,
       name AS variable_name
from user_identifiers
where object_type IN ('PACKAGE','PACKAGE BODY')
and usage = 'DECLARATION'
and type in ('VARIABLE','CONSTANT')
and usage_context_id in (
  select usage_id
  from user_identifiers
  where type = 'PACKAGE'
  );

我建议你的目标是生成的包列表。

如果您使用的是 11gR2,则常量不再导致此问题,因此您可以改用此查询:

select object_name AS package,
       type,
       name AS variable_name
from user_identifiers
where object_type IN ('PACKAGE','PACKAGE BODY')
and usage = 'DECLARATION'
and type = 'VARIABLE'
and usage_context_id in (
  select usage_id
  from user_identifiers
  where type = 'PACKAGE'
  );

【讨论】:

这不是我想要的。在 11g 中,包含所有 CONSTANT 包变量的包被认为是无状态的,但您的查询将返回它们。 eaolson,这不太正确。在 11gR1 中,常量 do 使包具有状态;这在 11gR2 中已修复。我已编辑问题以说明这一点。 我认为当用户模式中存在更多包时选择存在问题,因此应将子选择扩展到AND usage_context_id IN (SELECT usage_id FROM user_identifiers i2 WHERE TYPE = 'PACKAGE' AND i2.object_name = i.object_name) 注意加入 AND i2.object_name = i.object_name 最后,并且父 select 中的 user_identifiers 必须是别名 i。但是还是很好的答案! 谢谢@GWu,你可能是对的。我根据一个小的测试模式组成了这些查询。根据文档,user_identifiers.usage_id 在对象中是唯一的。

以上是关于有啥方法可以确定包在 Oracle 中是不是有状态?的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以使这个 UDF 具有确定性吗?

我们可以使用任何其他数据库,如 MariaDB 或 MongoDB 来在 Kafka Streams 中存储状态而不是 Rocks DB,有啥方法可以配置它吗?

有啥方法可以在 oracle 数据库中找到长时间运行的过程/包块?

View.isActivated() 有啥作用?

有啥方法可以跟踪数据库中oracle函数插入的行

@code java注解有啥作用