有状态pl/sql包是如何定义的?

use*_*949 3 java sql oracle plsql

我的 java 用户收到“找不到单元”错误,但我的包是有效的。另一篇文章提出了根本原因:我的包不能是无状态的。这是有道理的,但我不清楚Oracle对无状态的真正定义:

如果我从包的 SPEC 中删除所有声明的类型,它是否符合无状态的条件,或者我是否还必须从主体中删除所有 GLOBAL 变量?

Oracle 是这样定义无状态的:

“包声明的变量、常量和游标的值(在其规范或主体中)构成其包状态。如果 PL/SQL 包声明至少一个变量、常量或游标,则该包是有状态的;否则,它是无国籍的。”

这与这篇文章中提出的问题相同:

ORA-06508: PL/SQL: 找不到正在调用的程序单元

Ale*_*ole 5

如果我从包的 SPEC 中删除所有声明的类型,它是否符合无状态的条件,或者我是否还必须从主体中删除所有 GLOBAL 变量?

从身体上也是如此。规范中声明的变量(或常量、类型等)与主体中声明的变量(或常量、类型等)的唯一区别在于,主体中的变量是私有的,只能在主体内部引用,而规范中的变量则可以被看到并被引用。外部使用。

文档还提到编译时常量不会使包从 11gR2 开始阶段化,但由于您正在谈论变量,因此可能没有太大帮助。

(希望“全局”只是指在过程或函数外部声明的变量;这些变量仍然仅限于单个会话,它们不是跨会话的全局变量,正如该标签可能暗示的那样)。

您可以在运行程序遇到错误之前重置任何 JDBC 连接,这将使它们继续运行,但这取决于您正在执行的操作。例如,在 WebLogic 中,重新编译有状态包后,我可以重置连接池,这会关闭所有现有连接并打开新连接 - 这些连接具有新的会话,因此具有新的包实例化。

如果会话确实遇到错误,并且没有因此终止,则该会话中的下一个包调用应该获取该包的新版本并继续;但这仍然可能是一个问题并且有副作用。但是,如果您有连接池,则同一个程序可能会多次看到错误,因为它不断从池中获取新连接,并且其会话遇到状态问题。最终池中的所有连接要么获得新版本,要么被终止和替换。

正如 @pedantic 评论的那样,我没有明确指出,这仅适用于需要短暂且重复的更新周期的开发环境;即使使用无状态包,您也不应该在使用实时系统时将更改部署到它。

  • @user3119949 - 规范或正文中的类型声明不会使其成为有状态的。是的,我意识到实时更新可能存在操作原因,应该避免它们(无论如何,IMO)。有时你只需要在强加给你的限制内做你能做的事。无论如何... [这可能很有用](http://stackoverflow.com/a/11043498) 在部署上线之前检查问题。 (2认同)