软件开发数据库

db2 存储过程continue的问题

CREATE PROCEDURE DMINST.PROC_IDS_CUSTACC
(IN IN_WORK_DATE CHARACTER(8), 
IN IN_LAST_DATE CHARACTER(8), 
IN IN_Y_DAYS INTEGER, 
IN IN_J_DAYS INTEGER, 
IN IN_N_DAYS INTEGER
) 
LANGUAGE SQL
NOT DETERMINISTIC
CALLED ON NULL INPUT
MODIFIES SQL DATA
INHERIT SPECIAL REGISTERS
BEGIN 
/*变量声明*/
DECLARE SQLCODE INT DEFAULT 0; --SQL返回代码
DECLARE SQLSTATE CHAR(5) DEFAULT '00000'; --SQL默认返回代码00000返回成功

--定义游标
DECLARE CUR CURSOR FOR select ACCT_NO,CUST_NO,CUR from 
(SELECT ACCT_NO,CUST_NO,CUR FROM DWINST.FDS_DEPAGR UNION SELECT LN_ACCT_NO as acct_no,CUST_NO ,CURR_COD as cur FROM DWINST.FDS_LNACCT) a 
where ACCT_NO='9927000041499004010006310';


/*错误声明处理 */
--警告处理
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' 
BEGIN
SELECT SQLCODE,SQLSTATE INTO V_SQLCODE, V_SQLSTATE FROM SYSIBM.SYSDUMMY1;
SET V_MSG = CHAR(V_SQLCODE)||V_SQLSTATE||'WARNING' ;
SET V_PROC_FLG=1;
SET V_PROC_SUCC_FLG=0;
SET V_PROC_STM=NULL;
SET V_PROC_ETM=NULL;
CALL DMINST.PROC_BAH_LOG(V_PROC_ID, V_PROC_NAME ,V_PROC_STM,V_PROC_ETM, V_PROC_FLG, V_PROC_SUCC_FLG, V_MSG);
END;

--出错处理,退出
DECLARE exit HANDLER FOR SQLEXCEPTION
BEGIN
SELECT SQLCODE,SQLSTATE INTO V_SQLCODE, V_SQLSTATE FROM SYSIBM.SYSDUMMY1;
SET V_MSG = CHAR(V_SQLCODE)||V_SQLSTATE||'ERROR' ;
SET V_PROC_FLG=2;
SET V_PROC_SUCC_FLG=1;
SET V_PROC_STM=NULL;
SET V_PROC_ETM=CURRENT TIMESTAMP;
ROLLBACK ;
CALL DMINST.PROC_BAH_LOG(V_PROC_ID, V_PROC_NAME ,V_PROC_STM,V_PROC_ETM, V_PROC_FLG, V_PROC_SUCC_FLG, V_MSG);

END;
/* 处理主程序开始 */

--打开游标
OPEN CUR;
FETCH_JG_LOOP: LOOP
FETCH CUR INTO V_ACCT_NO,V_CUST_NO,V_CUR_COD;
IF SQLCODE !=0 THEN
LEAVE FETCH_JG_LOOP;
END IF; 
--计算存款积数
SELECT CASE WHEN SUBSTR(V_WORK_DATE,7,2)='01' THEN A.AMT ELSE A.AMT+COALESCE(B.M_DEP_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4) IN('0101','0401','0701','1001') THEN A.AMT ELSE A.AMT+COALESCE(B.Q_DEP_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4)='0101' THEN A.AMT ELSE A.AMT+COALESCE(B.Y_DEP_ACC,0) END INTO V_M_DEP_ACC,V_Q_DEP_ACC,V_Y_DEP_ACC FROM DWINST.FDS_DEPAGR A LEFT JOIN DMINST.IDS_CUSTACC_FB B ON A.ACCT_NO=B.ACCT_NO AND A.CUR=B.CUR_COD AND B.DT=V_LAST_DATE WHERE A.ACCT_NO=V_ACCT_NO AND A.CUR=V_CUR_COD ;
if SQLSTATE='02000' then
return 1;
end if;
--计算存款日均
SET V_M_AVE_DEP=V_M_DEP_ACC/V_Y_DAYS;
SET V_Q_AVE_DEP=V_Q_DEP_ACC/V_J_DAYS;
SET V_Y_AVE_DEP=V_Y_DEP_ACC/V_N_DAYS;

--计算协定存款积数
SELECT CASE WHEN SUBSTR(V_WORK_DATE,7,2)='01' THEN A.AGR_AMT ELSE A.AGR_AMT+COALESCE(B.M_AGR_DEP_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4) IN('0101','0401','0701','1001') THEN A.AGR_AMT ELSE A.AGR_AMT+COALESCE(B.Q_AGR_DEP_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4)='0101' THEN A.AGR_AMT ELSE A.AGR_AMT+COALESCE(B.Y_AGR_DEP_ACC,0) END INTO V_M_AGR_DEP_ACC,V_Q_AGR_DEP_ACC,V_Y_AGR_DEP_ACC FROM DWINST.FDS_DEPAGR A LEFT JOIN DMINST.IDS_CUSTACC_FB B ON A.ACCT_NO=B.ACCT_NO AND A.CUR=B.CUR_COD AND B.DT=V_LAST_DATE WHERE A.ACCT_NO=V_ACCT_NO AND A.CUR=V_CUR_COD ;
if SQLSTATE='02000' then
return 2;
end if;
--计算协定存款日均
SET V_M_AGR_AVE_DEP=V_M_AGR_DEP_ACC/V_Y_DAYS;
SET V_Q_AGR_AVE_DEP=V_Q_AGR_DEP_ACC/V_J_DAYS;
SET V_Y_AGR_AVE_DEP=V_Y_AGR_DEP_ACC/V_N_DAYS;


--计算贷款积数
SELECT CASE WHEN SUBSTR(V_WORK_DATE,7,2)='01' THEN A.LN_BAL ELSE A.LN_BAL+COALESCE(B.M_LN_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4) IN('0101','0401','0701','1001') THEN A.LN_BAL ELSE A.LN_BAL+COALESCE(B.Q_LN_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4)='0101' THEN A.LN_BAL ELSE A.LN_BAL+COALESCE(B.Y_LN_ACC,0) END INTO V_M_LN_ACC,V_Q_LN_ACC,V_Y_LN_ACC FROM DWINST.FDS_LNACCT A LEFT JOIN DMINST.IDS_CUSTACC_FB B ON A.CURR_COD=B.CUR_COD AND A.LN_ACCT_NO=B.ACCT_NO AND B.DT=V_LAST_DATE WHERE A.LN_ACCT_NO=V_ACCT_NO AND A.CURR_COD=V_CUR_COD ;
if SQLSTATE='02000' then
return 3;
end if;
--计算贷款积数
SET V_M_AVE_LN=V_M_LN_ACC/V_Y_DAYS;
SET V_Q_AVE_LN=V_Q_LN_ACC/V_J_DAYS;
SET V_Y_AVE_LN=V_Y_LN_ACC/V_N_DAYS;


INSERT INTO DMINST.IDS_CUSTACC(ACCT_NO,CUST_NO,CUR_COD,M_DEP_ACC,Q_DEP_ACC,Y_DEP_ACC,M_AVE_DEP,Q_AVE_DEP,Y_AVE_DEP,M_AGR_DEP_ACC,Q_AGR_DEP_ACC,Y_AGR_DEP_ACC,M_AGR_AVE_DEP,Q_AGR_AVE_DEP,Y_AGR_AVE_DEP,M_LN_ACC,Q_LN_ACC,Y_LN_ACC,M_AVE_LN,Q_AVE_LN,Y_AVE_LN) VALUES(V_ACCT_NO,V_CUST_NO,V_CUR_COD,V_M_DEP_ACC,V_Q_DEP_ACC,V_Y_DEP_ACC,V_M_AVE_DEP,V_Q_AVE_DEP,V_Y_AVE_DEP,V_M_AGR_DEP_ACC,V_Q_AGR_DEP_ACC,V_Y_AGR_DEP_ACC,V_M_AGR_AVE_DEP,V_Q_AGR_AVE_DEP,V_Y_AGR_AVE_DEP,V_M_LN_ACC,V_Q_LN_ACC,V_Y_LN_ACC,V_M_AVE_LN,V_Q_AVE_LN,V_Y_AVE_LN);
if SQLSTATE='02000' then
return 4;
end if;
END LOOP FETCH_JG_LOOP; 
CLOSE CUR;




COMMIT;
END;

现在的问题是,在return 3那个地方捕捉到02000了,捕捉到之后继续执行,是死循环执行。。。。不断的往DMINST.IDS_CUSTACC这个表插数据,这是为什么呢?我定义的游标只能查出一条数。按理说插入一条数据就完了,可现在是无限往里插同样的一条数据,为什么会这样子?
参与10

9同行回答

daijiangbodaijiangbo项目经理山东众阳软件有限公司
异常处理需要放在定义区,不能放在使用游标的里面。ninth 发表于 2011-11-4 11:28     :handshake 灰常感谢显示全部
异常处理需要放在定义区,不能放在使用游标的里面。
ninth 发表于 2011-11-4 11:28



    :handshake 灰常感谢收起
软件开发 · 2011-11-04
浏览520
daijiangbodaijiangbo项目经理山东众阳软件有限公司
你原来的判断方法:当游标为空时,SQLSTATE为 '02000' ,这时会跳转到异常处理程序,等你异常结束,会执行 ...ninth 发表于 2011-11-3 17:30     嗯,这个我明白了, DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' 异常处理只能放在游标定义之后吗?不能放在使用游标的里面...显示全部
你原来的判断方法:当游标为空时,SQLSTATE为 '02000' ,这时会跳转到异常处理程序,等你异常结束,
会执行 ...
ninth 发表于 2011-11-3 17:30



    嗯,这个我明白了, DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' 异常处理只能放在游标定义之后吗?不能放在使用游标的里面?收起
软件开发 · 2011-11-04
浏览520
ninthninth数据库管理员拓维信息系统股份有限公司
你原来的判断方法:FETCH CUR INTO V_ACCT_NO,V_CUST_NO,V_CUR_COD; IF SQLCODE !=0 THEN LEAVE FETCH_JG_LOOP; END IF; 当游标为空时,SQLSTATE为 '02000' ,这时会跳转到异常处理程序,等你异常结束,会执行IF SQLCODE !=0 THENLEAVE FETCH_JG_LOOP;END IF; 判断,实际上这时SQLCODE ...显示全部
你原来的判断方法:
FETCH CUR INTO V_ACCT_NO,V_CUST_NO,V_CUR_COD;
IF SQLCODE !=0 THEN
LEAVE FETCH_JG_LOOP;
END IF; 
当游标为空时,SQLSTATE为 '02000' ,这时会跳转到异常处理程序,等你异常结束,
会执行IF SQLCODE !=0 THEN
LEAVE FETCH_JG_LOOP;
END IF;
判断,实际上这时SQLCODE 为0,除非你的异常处理最后异步出错导致SQLCODE 不为0,正常情况下你的SQLCODE 肯定为0,所以你的程序就会进入到死循环。收起
互联网服务 · 2011-11-03
浏览505
daijiangbodaijiangbo项目经理山东众阳软件有限公司
回复 5# ninth     /*错误声明处理 */--警告处理DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' BEGINSET at_end = 1;SELECT SQLCODE,SQLSTATE INTO V_SQLCODE, V_SQLSTATE FROM SYSIBM.SYSDUMMY1;SET V_MSG = CHAR(V_SQLCODE)||V_SQLSTATE||'WARNING' ;SET ...显示全部
回复 5# ninth


    /*错误声明处理 */
--警告处理
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000'
BEGIN
SET at_end = 1;
SELECT SQLCODE,SQLSTATE INTO V_SQLCODE, V_SQLSTATE FROM SYSIBM.SYSDUMMY1;
SET V_MSG = CHAR(V_SQLCODE)||V_SQLSTATE||'WARNING' ;
SET V_PROC_FLG=1;
SET V_PROC_SUCC_FLG=0;
SET V_PROC_STM=NULL;
SET V_PROC_ETM=NULL;
CALL DMINST.PROC_BAH_LOG(V_PROC_ID, V_PROC_NAME ,V_PROC_STM,V_PROC_ETM, V_PROC_FLG, V_PROC_SUCC_FLG, V_MSG);
END;
假设不加SET at_end = 1这一句,他就会成死循环吗?DECLARE CONTINUE HANDLER FOR SQLSTATE '02000'
这一句的原理是什么呀,为什么会死循环?收起
软件开发 · 2011-11-03
浏览531
ninthninth数据库管理员拓维信息系统股份有限公司
你的程序判断游标结束有些问题。CREATE PROCEDURE DMINST.PROC_IDS_CUSTACC(IN IN_WORK_DATE CHARACTER(8), IN IN_LAST_DATE CHARACTER(8), IN IN_Y_DAYS INTEGER, IN IN_J_DAYS INTEGER, IN IN_N_DAYS INTEGER) LANGUAGE SQLNOT DETERMINISTICCALLED ON NULL INPUTMODI...显示全部
你的程序判断游标结束有些问题。
CREATE PROCEDURE DMINST.PROC_IDS_CUSTACC
(IN IN_WORK_DATE CHARACTER(8),
IN IN_LAST_DATE CHARACTER(8),
IN IN_Y_DAYS INTEGER,
IN IN_J_DAYS INTEGER,
IN IN_N_DAYS INTEGER
)
LANGUAGE SQL
NOT DETERMINISTIC
CALLED ON NULL INPUT
MODIFIES SQL DATA
INHERIT SPECIAL REGISTERS
BEGIN
/*变量声明*/
DECLARE SQLCODE INT DEFAULT 0; --SQL返回代码
DECLARE SQLSTATE CHAR(5) DEFAULT '00000'; --SQL默认返回代码00000返回成功
DECLARE at_end INTEGER DEFAULT 0;


--定义游标
DECLARE CUR CURSOR FOR select ACCT_NO,CUST_NO,CUR from
(SELECT ACCT_NO,CUST_NO,CUR FROM DWINST.FDS_DEPAGR UNION SELECT LN_ACCT_NO as acct_no,CUST_NO ,CURR_COD as cur FROM DWINST.FDS_LNACCT) a
where ACCT_NO='9927000041499004010006310';


/*错误声明处理 */
--警告处理
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000'
BEGIN
SET at_end = 1;
SELECT SQLCODE,SQLSTATE INTO V_SQLCODE, V_SQLSTATE FROM SYSIBM.SYSDUMMY1;
SET V_MSG = CHAR(V_SQLCODE)||V_SQLSTATE||'WARNING' ;
SET V_PROC_FLG=1;
SET V_PROC_SUCC_FLG=0;
SET V_PROC_STM=NULL;
SET V_PROC_ETM=NULL;
CALL DMINST.PROC_BAH_LOG(V_PROC_ID, V_PROC_NAME ,V_PROC_STM,V_PROC_ETM, V_PROC_FLG, V_PROC_SUCC_FLG, V_MSG);
END;

--出错处理,退出
DECLARE exit HANDLER FOR SQLEXCEPTION
BEGIN
SELECT SQLCODE,SQLSTATE INTO V_SQLCODE, V_SQLSTATE FROM SYSIBM.SYSDUMMY1;
SET V_MSG = CHAR(V_SQLCODE)||V_SQLSTATE||'ERROR' ;
SET V_PROC_FLG=2;
SET V_PROC_SUCC_FLG=1;
SET V_PROC_STM=NULL;
SET V_PROC_ETM=CURRENT TIMESTAMP;
ROLLBACK ;
CALL DMINST.PROC_BAH_LOG(V_PROC_ID, V_PROC_NAME ,V_PROC_STM,V_PROC_ETM, V_PROC_FLG, V_PROC_SUCC_FLG, V_MSG);

END;
/* 处理主程序开始 */

--打开游标
OPEN CUR;
FETCH_JG_LOOP: LOOP
FETCH CUR INTO V_ACCT_NO,V_CUST_NO,V_CUR_COD;
IF at_end = 1 THEN
LEAVE FETCH_JG_LOOP;
END IF;
--计算存款积数
SELECT CASE WHEN SUBSTR(V_WORK_DATE,7,2)='01' THEN A.AMT ELSE A.AMT+COALESCE(B.M_DEP_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4) IN('0101','0401','0701','1001') THEN A.AMT ELSE A.AMT+COALESCE(B.Q_DEP_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4)='0101' THEN A.AMT ELSE A.AMT+COALESCE(B.Y_DEP_ACC,0) END INTO V_M_DEP_ACC,V_Q_DEP_ACC,V_Y_DEP_ACC FROM DWINST.FDS_DEPAGR A LEFT JOIN DMINST.IDS_CUSTACC_FB B ON A.ACCT_NO=B.ACCT_NO AND A.CUR=B.CUR_COD AND B.DT=V_LAST_DATE WHERE A.ACCT_NO=V_ACCT_NO AND A.CUR=V_CUR_COD ;

--计算存款日均
SET V_M_AVE_DEP=V_M_DEP_ACC/V_Y_DAYS;
SET V_Q_AVE_DEP=V_Q_DEP_ACC/V_J_DAYS;
SET V_Y_AVE_DEP=V_Y_DEP_ACC/V_N_DAYS;

--计算协定存款积数
SELECT CASE WHEN SUBSTR(V_WORK_DATE,7,2)='01' THEN A.AGR_AMT ELSE A.AGR_AMT+COALESCE(B.M_AGR_DEP_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4) IN('0101','0401','0701','1001') THEN A.AGR_AMT ELSE A.AGR_AMT+COALESCE(B.Q_AGR_DEP_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4)='0101' THEN A.AGR_AMT ELSE A.AGR_AMT+COALESCE(B.Y_AGR_DEP_ACC,0) END INTO V_M_AGR_DEP_ACC,V_Q_AGR_DEP_ACC,V_Y_AGR_DEP_ACC FROM DWINST.FDS_DEPAGR A LEFT JOIN DMINST.IDS_CUSTACC_FB B ON A.ACCT_NO=B.ACCT_NO AND A.CUR=B.CUR_COD AND B.DT=V_LAST_DATE WHERE A.ACCT_NO=V_ACCT_NO AND A.CUR=V_CUR_COD ;

--计算协定存款日均
SET V_M_AGR_AVE_DEP=V_M_AGR_DEP_ACC/V_Y_DAYS;
SET V_Q_AGR_AVE_DEP=V_Q_AGR_DEP_ACC/V_J_DAYS;
SET V_Y_AGR_AVE_DEP=V_Y_AGR_DEP_ACC/V_N_DAYS;


--计算贷款积数
SELECT CASE WHEN SUBSTR(V_WORK_DATE,7,2)='01' THEN A.LN_BAL ELSE A.LN_BAL+COALESCE(B.M_LN_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4) IN('0101','0401','0701','1001') THEN A.LN_BAL ELSE A.LN_BAL+COALESCE(B.Q_LN_ACC,0) END,CASE WHEN SUBSTR(V_WORK_DATE,5,4)='0101' THEN A.LN_BAL ELSE A.LN_BAL+COALESCE(B.Y_LN_ACC,0) END INTO V_M_LN_ACC,V_Q_LN_ACC,V_Y_LN_ACC FROM DWINST.FDS_LNACCT A LEFT JOIN DMINST.IDS_CUSTACC_FB B ON A.CURR_COD=B.CUR_COD AND A.LN_ACCT_NO=B.ACCT_NO AND B.DT=V_LAST_DATE WHERE A.LN_ACCT_NO=V_ACCT_NO AND A.CURR_COD=V_CUR_COD ;

--计算贷款积数
SET V_M_AVE_LN=V_M_LN_ACC/V_Y_DAYS;
SET V_Q_AVE_LN=V_Q_LN_ACC/V_J_DAYS;
SET V_Y_AVE_LN=V_Y_LN_ACC/V_N_DAYS;


INSERT INTO DMINST.IDS_CUSTACC(ACCT_NO,CUST_NO,CUR_COD,M_DEP_ACC,Q_DEP_ACC,Y_DEP_ACC,M_AVE_DEP,Q_AVE_DEP,Y_AVE_DEP,M_AGR_DEP_ACC,Q_AGR_DEP_ACC,Y_AGR_DEP_ACC,M_AGR_AVE_DEP,Q_AGR_AVE_DEP,Y_AGR_AVE_DEP,M_LN_ACC,Q_LN_ACC,Y_LN_ACC,M_AVE_LN,Q_AVE_LN,Y_AVE_LN) VALUES(V_ACCT_NO,V_CUST_NO,V_CUR_COD,V_M_DEP_ACC,V_Q_DEP_ACC,V_Y_DEP_ACC,V_M_AVE_DEP,V_Q_AVE_DEP,V_Y_AVE_DEP,V_M_AGR_DEP_ACC,V_Q_AGR_DEP_ACC,V_Y_AGR_DEP_ACC,V_M_AGR_AVE_DEP,V_Q_AGR_AVE_DEP,V_Y_AGR_AVE_DEP,V_M_LN_ACC,V_Q_LN_ACC,V_Y_LN_ACC,V_M_AVE_LN,V_Q_AVE_LN,V_Y_AVE_LN);

END LOOP FETCH_JG_LOOP;
CLOSE CUR;




COMMIT;
END;收起
互联网服务 · 2011-11-02
浏览558
weiruan85weiruan85数据库管理员ibm
在存储过程里边加上一些调试信息,这样可以定位问题,  存储过程调试有时候也可以把无用的先删掉,然后执行找出问题的原因。 总之这个跟技能无关了,讲究套路显示全部
在存储过程里边加上一些调试信息,这样可以定位问题,  存储过程调试有时候也可以把无用的先删掉,然后执行找出问题的原因。 总之这个跟技能无关了,讲究套路收起
政府机关 · 2011-11-01
浏览510
hchaohchao网站运营经理TWT
回复 1# daijiangbo     超过三天,无专家版主做出回答与说明。社区承诺奖励大米:20米。问题在DB2china社区中无人回答一般有两种,一种是真没有人能知道答案,一种是你没有描述清楚问题,无人能看明白,所以也无法解答。希望你再把问题看看清楚,是不是需要还有要补充的。...显示全部
回复 1# daijiangbo


    超过三天,无专家版主做出回答与说明。社区承诺奖励大米:20米。
问题在DB2china社区中无人回答一般有两种,一种是真没有人能知道答案,一种是你没有描述清楚问题,无人能看明白,所以也无法解答。希望你再把问题看看清楚,是不是需要还有要补充的。收起
互联网服务 · 2011-10-31
浏览533
daijiangbodaijiangbo项目经理山东众阳软件有限公司
:(没人回答呀???显示全部
:(没人回答呀???收起
软件开发 · 2011-10-28
浏览514
ninthninth数据库管理员拓维信息系统股份有限公司
异常处理需要放在定义区,不能放在使用游标的里面。显示全部
异常处理需要放在定义区,不能放在使用游标的里面。收起
互联网服务 · 2011-10-26
浏览513

提问者

daijiangbo
项目经理山东众阳软件有限公司
擅长领域: AIXUnix服务器

相关问题

相关资料

相关文章

问题状态

  • 发布时间:2011-10-26
  • 关注会员:1 人
  • 问题浏览:3717
  • 最近回答:2011-11-04
  • X社区推广