如何为循环编写异常?
Posted
技术标签:
【中文标题】如何为循环编写异常?【英文标题】:How to write exception for a loop? 【发布时间】:2015-01-15 21:58:02 【问题描述】:create or replace PROCEDURE BBVA_SP_MIGRATE_CEG
(
--parameter pass
x_migration_status OUT varchar2
) AS
--variable declarations
v_contract_number kndtctc.tctc_cncclipu%type;
v_customer_code kndtcct.tcct_cncctco%type;
v_customer_name varchar2(50);
v_customer_number varchar2(50);
v_account_number varchar2(50);
v_contact_name varchar2(50);
v_phone_number varchar2(25);
v_email_id varchar2(50);
v_connection_type varchar2(50);
v_LBX_OUT1 varchar2(10);
v_LBX_OUT2 varchar2(10);
v_LBX_OUT3 varchar2(10);
v_LBX_OUT4 varchar2(10);
v_LBX_OUT5 varchar2(10);
v_LBX_OUT6 varchar2(10);
v_LBX_OUT7 varchar2(10);
v_LBX_OUT8 varchar2(10);
v_LBX_OUT9 varchar2(10);
v_STOPFILE_IN1 varchar2(10);
v_ARP_OUT1 varchar2(10);
v_ARP_OUT2 varchar2(10);
v_ARP_OUT3 varchar2(10);
v_ARP_OUT4 varchar2(10);
v_ARP_OUT5 varchar2(10);
v_ARP_OUT6 varchar2(10);
v_ARP_OUT7 varchar2(10);
v_ARP_OUT8 varchar2(10);
v_ARP_OUT9 varchar2(10);
v_ARP_IN1 varchar2(10);
v_ARP_IN2 varchar2(10);
v_ARP_IN3 varchar2(10);
v_ARP_IN4 varchar2(10);
v_ARP_IN5 varchar2(10);
v_ARP_IN6 varchar2(10);
v_ARP_IN7 varchar2(10);
v_ARP_IN8 varchar2(10);
v_ARP_IN9 varchar2(10);
v_ACH_OUT1 varchar2(10);
v_ACH_OUT2 varchar2(10);
v_ACH_OUT3 varchar2(10);
v_ACH_OUT4 varchar2(10);
v_ACH_OUT5 varchar2(10);
v_ACH_OUT6 varchar2(10);
v_ACH_OUT7 varchar2(10);
v_ACH_OUT8 varchar2(10);
v_ACH_OUT9 varchar2(10);
v_ACH_IN1 varchar2(10);
v_ACH_IN2 varchar2(10);
v_ACH_IN3 varchar2(10);
v_ACH_IN4 varchar2(10);
v_ACH_IN5 varchar2(10);
v_ACH_IN6 varchar2(10);
v_ACH_IN7 varchar2(10);
v_ACH_IN8 varchar2(10);
v_ACH_IN9 varchar2(10);
v_ANL822FILE_OUT1 varchar2(10);
v_DEPOSITRACKFILE_OUT1 varchar2(10);
v_EDI_OUT1 varchar2(10);
v_CDA_OUT1 varchar2(10);
v_BAI_OUT1 varchar2(10);
v_ICL_IN1 varchar2(10);
v_RECONFILE_OUT1 varchar2(10);
v_SUSPENDCARDFILE_IN1 varchar2(10);
V_ceg_record_found varchar2(1);
v_REC_NUMBER number;
V_BANKCODE varchar2(25);
v_status varchar2(10);
v_timestamp TIMESTAMP(6):=systimestamp;
v_tx VARCHAR2(2000);
v_sysdate DATE := SYSDATE;
v_tz varchar2(2000);
v_num_err exception;
BEGIN
v_tx:=to_char(v_timestamp,'DD-MON-RR HH.MI.SSXFF AM');
v_tz:=to_char(v_sysdate, 'DD-MON-RR');
x_migration_status:='FAIL';
V_ceg_record_found:='N';
<<outer_loop>>
for in_rec_number IN 1..500 LOOP
SELECT CUSTOMERNAME,
CUSTOMERNUMBER,
ACCOUNTNUMBER,
CONTACTNAME,
CONTACTPHONE,
CONTACTEMAIL,
CONNECTIONTYPE,
LBX_OUT1,
LBX_OUT2,
LBX_OUT3,
LBX_OUT4,
LBX_OUT5,
LBX_OUT6,
LBX_OUT7,
LBX_OUT8,
LBX_OUT9,
STOPFILE_IN1,
ARP_OUT1,
ARP_OUT2,
ARP_OUT3,
ARP_OUT4,
ARP_OUT5,
ARP_OUT6,
ARP_OUT7,
ARP_OUT8,
ARP_OUT9,
ARP_IN1,
ARP_IN2,
ARP_IN3,
ARP_IN4,
ARP_IN5,
ARP_IN6,
ARP_IN7,
ARP_IN8,
ARP_IN9,
ACH_OUT1,
ACH_OUT2,
ACH_OUT3,
ACH_OUT4,
ACH_OUT5,
ACH_OUT6,
ACH_OUT7,
ACH_OUT8,
ACH_OUT9,
ACH_IN1,
ACH_IN2,
ACH_IN3,
ACH_IN4,
ACH_IN5,
ACH_IN6,
ACH_IN7,
ACH_IN8,
ACH_IN9,
ANL822FILE_OUT1,
DEPOSITRACKFILE_OUT1,
EDI_OUT1,
CDA_OUT1,
BAI_OUT1,
ICL_IN1,
RECONFILE_OUT1,
SUSPENDCARDFILE_IN1,
'Y',
CEG_ID,
BANKCODE,
CEG_STATUS
INTO
v_customer_name,
v_customer_number,
v_account_number,
v_contact_name,
v_phone_number,
v_email_id,
v_connection_type,
v_LBX_OUT1,
v_LBX_OUT2,
v_LBX_OUT3,
v_LBX_OUT4,
v_LBX_OUT5,
v_LBX_OUT6,
v_LBX_OUT7,
v_LBX_OUT8,
v_LBX_OUT9,
v_STOPFILE_IN1,
v_ARP_OUT1,
v_ARP_OUT2,
v_ARP_OUT3,
v_ARP_OUT4,
v_ARP_OUT5,
v_ARP_OUT6,
v_ARP_OUT7,
v_ARP_OUT8,
v_ARP_OUT9,
v_ARP_IN1,
v_ARP_IN2,
v_ARP_IN3,
v_ARP_IN4,
v_ARP_IN5,
v_ARP_IN6,
v_ARP_IN7,
v_ARP_IN8,
v_ARP_IN9,
v_ACH_OUT1,
v_ACH_OUT2,
v_ACH_OUT3,
v_ACH_OUT4,
v_ACH_OUT5,
v_ACH_OUT6,
v_ACH_OUT7,
v_ACH_OUT8,
v_ACH_OUT9,
v_ACH_IN1,
v_ACH_IN2,
v_ACH_IN3,
v_ACH_IN4,
v_ACH_IN5,
v_ACH_IN6,
v_ACH_IN7,
v_ACH_IN8,
v_ACH_IN9,
v_ANL822FILE_OUT1,
v_DEPOSITRACKFILE_OUT1,
v_EDI_OUT1,
v_CDA_OUT1,
v_BAI_OUT1,
v_ICL_IN1,
v_RECONFILE_OUT1,
v_SUSPENDCARDFILE_IN1,
v_CEG_RECORD_FOUND,
v_REC_NUMBER,
V_BANKCODE,
V_Status
FROM t_ceg_migration
WHERE
upper(CEG_STATUS) = 'RECEIVED' and
in_rec_number = to_number(CEG_ID);
IF v_CEG_RECORD_FOUND = 'Y' THEN
DBMS_OUTPUT.PUT_LINE (in_rec_number);
-- get next sequence numbers
V_CONTRACT_NUMBER := tctc_cncclipu_seq.nextval;
V_CUSTOMER_CODE := tcct_cncctco_seq.nextval;
--then inserts into other tables, not relevant to the exception--
x_migration_status := to_char(v_contract_number);
UPDATE t_Ceg_migration
set CEG_status = 'IMPORTED'
where
upper(CEG_STATUS) = 'RECEIVED' and
in_rec_number = to_number(CEG_ID);
end if; -- ceg_record_found
这是我在所有更新应该发生在受此过程影响的其他表之后放置异常的地方。
BEGIN
IF v_rec_number > 500 THEN
RAISE v_num_err;
END IF;
EXCEPTION
WHEN v_num_err THEN
dbms_output.put_line ('Error: Try Again');
End;
end LOOP outer_loop;
END BBVA_SP_MIGRATE_CEG;
异常会去哪里以确保在运行异常之前显示有效记录?
【问题讨论】:
你能再展示一些你的上下文过程吗? 两行源码是不够的。请展示您的完整程序并描述它的数据。 variable dec: x_migration_status OUT varchar2 ) AS --variable declarations v_contract_number kndtctc.tctc_cncclipu%type; v_customer_code kndtcct.tcct_cncctco%type; v_customer_name varchar2(50); v_customer_number varchar2(50); v_account_number varchar2(50); 正文:开始 v_tx:=to_char(v_timestamp,'DD-MON-RR HH.MI.SSXFF AM'); v_tz:=to_char(v_sysdate, 'DD-MON-RR'); x_migration_status:='失败'; V_ceg_record_found:='N'; > for in_rec_number IN 1..500 LOOP SELECT CUSTOMERNAME、CUSTOMERNUMBER、ACCOUNTNUMBER、CONTACTNAME、CONTACTPHONE, 请将代码和重要的新信息放入问题中,而不是 cmets。 【参考方案1】:您已将异常处理程序放在最后,这意味着一旦遇到异常,它就会退出循环并在最后的异常块中处理。如果您希望进程继续,则将异常处理程序本地添加到循环中的 SELECT 语句中。
PROCEDURE bbva_sp_migrate_ceg(x_migration_status OUT VARCHAR2 )
AS
v_contract_number kndtctc.tctc_cncclipu%TYPE;
v_customer_code kndtcct.tcct_cncctco%TYPE;
v_customer_name VARCHAR2(50);
v_customer_number VARCHAR2(50);
v_account_number VARCHAR2(50);
BEGIN
v_tx:=To_char(v_timestamp,'DD-MON-RR HH.MI.SSXFF AM');
v_tz:=To_char(v_sysdate, 'DD-MON-RR');
x_migration_status:='FAIL';
v_ceg_record_found:='N';
<<outer_loop>>
FOR in_rec_number IN 1..500
LOOP
BEGIN
SELECT customername,
customernumber,
accountnumber,
contactname,
contactphone,
FROM t_ceg_migration
WHERE upper(ceg_status) = 'RECEIVED'
AND in_rec_number = to_number(ceg_id);
IF v_ceg_record_found = 'Y' THEN
dbms_output.Put_line (in_rec_number); -- get next sequence numbers
V_CONTRACT_NUMBER := tctc_cncclipu_seq.nextval;
V_CUSTOMER_CODE := tcct_cncctco_seq.nextval;
x_migration_status := To_char(v_contract_number);
UPDATE t_ceg_migration
SET ceg_status = 'IMPORTED'
WHERE upper(ceg_status) = 'RECEIVED'
AND in_rec_number = to_number(ceg_id);
END IF; -- ceg_record_found
EXCEPTION
WHEN no_data_found THEN
dbms_output.Put_line ('No data found for: '
|| v_contract_number);
WHEN OTHERS THEN
dbms_output.Put_line ('Error for : '
|| v_contract_number);
dbms_output.Put_line(dbms_utility.format_error_backtrace);
END
END LOOP outer_loop;
END bbva_sp_migrate_ceg;
这样,如果循环的特定迭代出现一些错误,异常会被捕获、处理,错误消息写入缓冲区,然后它会继续循环的下一次迭代
在相关说明中,强烈建议您将错误写入表而不是缓冲区/
【讨论】:
@AlexPoole 哎呀,你本来想早点删除它们,但忘了。以上是关于如何为循环编写异常?的主要内容,如果未能解决你的问题,请参考以下文章