ORACLE 包中的常量 与 ORA-04068 错误
最近我在做一个项目,有些业务是用 存储过程写的。里面有好几个包,如 PG_COMMON,PG_TO等等还有一些其它包。
PG_COMMON包是目前共用的一个包,里面包括一些基础数据的检查什么的,其它包是按不同业务分类的,PG_TO就是其中的一个业务。
每个过程都含有属于自己业务区域的一些常量,有些包可能依赖其它包。
我们在开发过程遇到一个问题:我们的项目处于开发阶段,开发人员的应用服务器(如tomcat,jboss)可能一直处于运行状态。
但存储过程不免有些业务错误须要改动,或新增,或调整,而 java 端的开发人员也需要测试存储过程,每次测试出存储过程中的问题,
就直接改过程,然后重新编译了这个包,接着再测试时(没有重启jboss), ORACLE 出如下错误:
ORA-04068: 已丢弃程序包 的当前状态
ORA-04061: package "SCOTT.PG_TO" 的当前状态失效
我们重启jboss,便能正常运时。这样一来,每一次的过程改动都要重新编译包,还要重启jboss,让人不能接受。
在网上查了一些资料,并整理了一下:
这里我们先做一个测试,其中有 PG_COMMON包,PG_TO包。
PG_COMMON包如下:
其中里面有些常量和一个公共的方法。
SQL>
SQL> CREATE OR REPLACE PACKAGE PG_COMMON AS
2 -- 常量
3 C_CODE_ERROR CONSTANT VARCHAR2(10) := 'ERROR';
4 C_CODE_SUCCESS CONSTANT VARCHAR2(10) := 'SUCCESS';
5 --
6 FUNCTION SP_IS_EXIST_TO(I_TO NUMBER) RETURN BOOLEAN;
7
8 END PG_COMMON;
9 /
Package created
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY PG_COMMON AS
2 FUNCTION SP_IS_EXIST_TO(I_TO NUMBER) RETURN BOOLEAN IS
3 V_FLAG BOOLEAN := FALSE;
4 BEGIN
5 -- 不为空 返回 TRUE
6 IF I_TO IS NOT NULL THEN
7 V_FLAG := TRUE;
8 END IF;
9 RETURN V_FLAG;
10 END SP_IS_EXIST_TO;
11 END PG_COMMON;
12 /
Package body created
PG_TO包如下:
PG_TO 包也有属于自己的常量,并用到PG_COMMON包的常量。
SQL>
SQL> CREATE OR REPLACE PACKAGE PG_TO AS
2 -- TO 常量
3 C_TO_STATUS_OPEN CONSTANT VARCHAR2(10) := 'OPEN';
4 C_TO_STATUS_CLOSE CONSTANT VARCHAR2(10) := 'CLOSE';
5 C_TO_STATUS_CANCEL CONSTANT VARCHAR2(10) := 'CANCEL';
6
7 PROCEDURE SP_GET_TO_STATUS(I_TO IN NUMBER,
8 O_TO_STATUS OUT VARCHAR2,
9 O_CODE OUT VARCHAR2);
10
11 END PG_TO;
12 /
Package body created
PG_TO包明细的业务
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY PG_TO AS
2
3 PROCEDURE SP_GET_TO_STATUS(I_TO IN NUMBER,
4 O_TO_STATUS OUT VARCHAR2,
5 O_CODE OUT VARCHAR2) IS
6 V_FLAG BOOLEAN := FALSE;
7 BEGIN
8 -- 默认为失败
9 O_CODE := PG_COMMON.C_CODE_ERROR;
10
11 V_FLAG := PG_COMMON.SP_IS_EXIST_TO(I_TO => I_TO);
12 IF V_FLAG = TRUE THEN
13 -- 先默认为 OPEN
14 O_TO_STATUS := C_TO_STATUS_OPEN;
15 ELSE
16 -- TO 号不存在
17 RETURN;
18 END IF;
19
20 -- 成功
21 O_CODE := PG_COMMON.C_CODE_SUCCESS;
22 EXCEPTION
23 WHEN OTHERS THEN
24 RAISE;
25 END SP_GET_TO_STATUS;
26 END PG_TO;
27 /
Package body created
测试运行如下:
SQL> set serveroutput on;
SQL>
SQL> DECLARE
2 V_TO_NO VARCHAR2(10);
3 V_CODE VARCHAR2(10);
4 V_TO_STATUS VARCHAR2(10);
5 BEGIN
6
7 PG_TO.SP_GET_TO_STATUS(I_TO => V_TO_NO,
8 O_TO_STATUS => V_TO_STATUS,
9 O_CODE => V_CODE);
10
11 IF V_CODE = PG_COMMON.C_CODE_ERROR THEN
12 DBMS_OUTPUT.PUT_LINE(V_CODE);
13 END IF;
14 END ;
15 /
ERROR
PL/SQL procedure successfully completed
测试结果为 ERROR 过程成功运行
我们对 PG_TO 包体中 13,14行作改动,增加具体实现,并重新编译包 PG_TO。
-- 去掉默认,更为具体实现
SELECT t_*.status
INTO O_TO_STATUS
FROM t_*
WHERE t_*.TO = I_TO;
再运行 结果出错误:
SQL> /
DECLARE
V_TO_NO VARCHAR2(10);
V_CODE VARCHAR2(10);
V_TO_STATUS VARCHAR2(10);
BEGIN
PG_TO.SP_GET_TO_STATUS(I_TO => V_TO_NO,
O_TO_STATUS => V_TO_STATUS,
O_CODE => V_CODE);
IF V_CODE = PG_COMMON.C_CODE_ERROR THEN
DBMS_OUTPUT.PUT_LINE(V_CODE);
END IF;
END ;
ORA-04068: 已丢弃程序包 的当前状态
ORA-04061: package "SCOTT.PG_TO" 的当前状态失效
ORA-04065: 未执行, 已更改或删除 package "SCOTT.PG_TO"
ORA-06508: PL/SQL: 无法找到正在调用 : "SCOTT.PG_TO" 的程序单元
ORA-06512: 在 line 7
下一篇将解决此问题:
oracle 包中的常量(包括全局和私有)与 ORA-04068 错误 (二)
http://blog.youkuaiyun.com/kechengtan/article/details/6268450
http://blog.youkuaiyun.com/qshpeng/article/details/6424375