Oracle 当我使用异常处理程序第二次尝试后,仍然获得ORA-04068(包的现有状态已被丢弃)
我有以下测试设置:Oracle 当我使用异常处理程序第二次尝试后,仍然获得ORA-04068(包的现有状态已被丢弃),oracle,plsql,exception-handling,Oracle,Plsql,Exception Handling,我有以下测试设置: create or replace PACKAGE pkg_state AS FUNCTION get_variable RETURN VARCHAR2; END pkg_state; / create or replace PACKAGE BODY pkg_state AS g_pkg_variable NUMBER(10) := 2; --testa FUNCTION get_variable RETURN VARCHAR2 AS
create or replace PACKAGE pkg_state
AS
FUNCTION get_variable RETURN VARCHAR2;
END pkg_state;
/
create or replace PACKAGE BODY pkg_state
AS
g_pkg_variable NUMBER(10) := 2; --testa
FUNCTION get_variable
RETURN VARCHAR2
AS
BEGIN
RETURN 'FALSE ';
END get_variable;
END pkg_state;
/
下面是测试调用:
set serveroutput on;
DECLARE
v_ReturnValue VARCHAR2(500);
BEGIN
v_ReturnValue := PKG_STATE.get_variable();
DBMS_OUTPUT.PUT_LINE('v_ReturnValue = ' || v_ReturnValue);
exception when others then
DBMS_OUTPUT.PUT_LINE('ERROR');
--raise;
END;
如果我运行此程序并在另一个会话中更改包,我将得到错误ORA-04068->Expected
但是,如果我再次运行它(不再次更改包),它将再次失败(以及此后的每次尝试)
如果我重新抛出错误(删除“raise;”的注释),一切都会按预期进行:第一次出错;第二次成功
我认为它在第二次尝试时总是有效的。当我“吞咽”错误时,为什么不这样做?从来没有读过关于这个具体问题的东西
这似乎不可能捕获错误并尝试在用户未注意到任何错误的情况下再次拨打电话。
(DB 11.2.0.4)Oracle在每个会话的会话内存中保存一个已编译的包实例。如果包无效,将重新加载它 因此,需要传播此错误(raise)来清除无效的包
试图忽略包变量的无效状态是错误的做法 Oracle在每个会话的会话内存中保存一个已编译的包实例。如果包无效,将重新加载它 因此,需要传播此错误(raise)来清除无效的包
试图忽略包变量的无效状态是错误的做法 要处理此类问题,只需从异常块重新运行代码:
DECLARE
v_ReturnValue VARCHAR2(500);
BEGIN
v_ReturnValue := PKG_STATE.get_variable();
DBMS_OUTPUT.PUT_LINE('v_ReturnValue = ' || v_ReturnValue);
exception when others then
DBMS_OUTPUT.PUT_LINE('ERROR');
v_ReturnValue := PKG_STATE.get_variable();
DBMS_OUTPUT.PUT_LINE('v_ReturnValue = ' || v_ReturnValue);
END;
要处理此类问题,只需从异常块重新运行代码:
DECLARE
v_ReturnValue VARCHAR2(500);
BEGIN
v_ReturnValue := PKG_STATE.get_variable();
DBMS_OUTPUT.PUT_LINE('v_ReturnValue = ' || v_ReturnValue);
exception when others then
DBMS_OUTPUT.PUT_LINE('ERROR');
v_ReturnValue := PKG_STATE.get_variable();
DBMS_OUTPUT.PUT_LINE('v_ReturnValue = ' || v_ReturnValue);
END;
为什么要抓住错误?这种情况在生产环境中永远不会发生,除非您正在更新软件。我在开发过程中经常遇到这种情况,但在生产过程中从未遇到过问题。在生产过程中,当我们需要热修复程序而不能称为停机时,这种情况很少发生。1.)从理论上讲,抓住这个机会会很好,再次尝试运行您的逻辑,并在第二次失败时提高它。但这似乎不像我的例子所显示的那样有效。2.)我们有大量的旧代码和坏代码,这些代码有“when others”而没有重新出现错误。也许这有一些有用的提示:Thx Rene。我已经知道的大部分信息,但我对博客文章中的“陷阱和重试”部分感兴趣。如果您需要重新发送错误以使第二次呼叫正常工作,则此操作永远无法工作。为什么要捕获错误?这种情况在生产环境中永远不会发生,除非您正在更新软件。我在开发过程中经常遇到这种情况,但在生产过程中从未遇到过问题。在生产过程中,当我们需要热修复程序而不能称为停机时,这种情况很少发生。1.)从理论上讲,抓住这个机会会很好,再次尝试运行您的逻辑,并在第二次失败时提高它。但这似乎不像我的例子所显示的那样有效。2.)我们有大量的旧代码和坏代码,这些代码有“when others”而没有重新出现错误。也许这有一些有用的提示:Thx Rene。我已经知道的大部分信息,但我对博客文章中的“陷阱和重试”部分感兴趣。如果您需要重新发送错误以使第二次呼叫正常工作,则此操作永远无法工作。您尝试过吗?它不起作用。这是我的问题:如果你不在异常块中重新激活它,它就不会起作用……你试过了吗?它不起作用。这是我的问题:如果你不在异常块中重新激活它,它就不起作用了……“忽略”太苛刻了。也许我确切地知道现在什么状态被破坏了,这样我就可以捕捉到异常并将用户重定向到最后一步,在那里我知道一切都是有效的,而不会让用户看到错误。“忽略”太苛刻了。也许我确切地知道现在是什么状态被破坏了,这样我就可以捕获该异常并将用户重定向到最后一步,在这一步中,我知道一切都是有效的,而不会让用户看到错误。