我有一个JDBC会话引用PL / SQL包的场景。当我更改包体并重新编译它时,会话不会抛出任何异常,但是当我重新编译包规范时,它会抛出以下异常。我的问题是为什么当包体改变时会话不会抛出任何异常,如果我在包体中进行了更改,现有会话是否会看到更改?
ORA-04068: existing state of packages has been discarded
答案 0 :(得分:0)
如果PL / SQL包具有全局变量(常量或可修改),则认为包具有状态。如果更改包,则会重新初始化变量并丢失状态。
如果数据库会话已使用该程序包,则下次访问程序包时将收到ORA-04068异常。如果它处理异常,则可以继续使用该包而不会再次收到异常。当然,国家已经失败,新版本的套餐也适用。
对于没有全局变量的PL / SQL包,不会抛出任何错误。新版本的软件包立即适用于所有会话。
那么,如果在该会话中不再使用更改的包,为什么会期望会话抛出异常?这会带来更多问题,而不是增值。
答案 1 :(得分:0)
阅读" 更轻松的应用程序设计"和" 隐藏的实施细节"在Reasons to use Packages
最重要的是" 包装编写指南" (同一页)明确说明:
在包规范中,仅声明必须可见的项目 调用程序。
这种做法可以防止其他开发人员构建不安全的问题 依赖于您的实现细节并减少对您的需求 重新编译。
如果更改包规范,则必须重新编译 调用包的公共子程序的子程序。如果你 只更改包体,您无需重新编译 子程序。
答案 2 :(得分:0)
这是一个众所周知的问题。 在这里,您可以找到有关如何解决它的任何细节。 http://laurentschneider.com/wordpress/2010/12/how-to-solve-ora-4068.html
但是如果你对全局变量要非常小心!如果它们在您的包中使用,那么在其他程序使用它时不要编译您的包。
从dba的角度来看,通过v $ access视图可以知道谁在这个包上有“锁定”。所以你可以通过ddl上的触发器来引发编译。