我在程序中使用“下一个序列值”时出现问题。
我有'external'函数来返回Sequence的Next Value。 在我的程序中,我想将该序列的值分配给变量 并在我的游标中使用该变量(因为我在游标中使用了union语句)。
但它没有用。
CREATE OR REPLACE Procedure HR.insert_TBL_APP is
--declare variables for insert
v_TA_SNO VARCHAR2(10);
v_TA_SEQNO VARCHAR2(6);
v_TA_DESC VARCHAR2(10);
--declare variable to store the sequence number
var_TaSeqno varchar2(6);
-- Validation
v_check VARCHAR2 (10 Byte);
err_code varchar2(50);
err_msg varchar2(100);
v_table_name varchar2(50):='TBL_APP';
error_found exception;
cursor c1 is
select distinct TA_SNO,
TA_SEQNO,
TA_DESC
from (
SELECT hdr.FIRST_NO TA_SNO,
var_TaSeqno TA_SEQNO, -- using variable to assign the sequence no
hdr.descrip TA_DESC
FROM
FORMS_HDR hdr
WHERE
hdr.seco_name = 'TST121'
union
SELECT hdr.FIRST_NO TA_SNO,
var_TaSeqno TA_SEQNO, -- using variable to assign the sequence no
hdr.descrip TA_DESC
FROM
FORMS_HDR hdr
WHERE
hdr.seco_name = 'TST122');
begin
if c1%isopen then
close c1;
end if;
v_check:=null;
FOR i IN c1 LOOP
--assign variables for insert
v_TA_SNO := i.TA_SNO;
v_TA_SEQNO := i.TA_SEQNO;
v_TA_DESC := i.TA_DESC;
begin
-- calling the Function taSeqNoFunc and assign the
--sequence No into the variable var_TaSeqno
var_TaSeqno := HR.taSeqNoFunc();
select TA_SNO
into v_check
from TBL_APP a
where TA_SNO = i.TA_SNO
and TA_SEQNO =i.TA_SEQNO;
exception
when no_data_found then
--insert into target table
INSERT INTO TBL_APP (TA_SNO,
TA_SEQNO,
TA_DESC
)
values (v_TA_SNO,
v_TA_SEQNO,
v_TA_DESC
);
when others then
raise error_found;
end ;
end loop;
exception when error_found then
rollback;
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);
insert into TA_ERROR_LOG values (v_check,v_table_name,'An error
was encountered '||err_code||':'||err_msg,sysdate);
commit;
raise_application_error(err_code,err_msg);
end;
/
错误最终会在结尾附近进入raise_application_error:
“ORA-21000:raise_application_error为1的错误编号参数超出范围”
请帮帮我。谢谢。
答案 0 :(得分:3)
raise_application_error()
过程是内置的Oracle PL / SQL。它提供了我们可以将自定义消息与用户定义的异常相关联的内容。用户定义的异常必须具有-20999到-20000范围内的数字。 Find out more
由于内部EXCEPTION块中的代码,您收到此错误:
when others then
raise error_found;
您正在引发用户定义的异常,但是您没有使用EXCEPTION_INIT pragma与错误号相关联。 Find out more。因此,Oracle默认为SQLCODE = 1
,SQLERRM = 'User-Defined Exception'
。
显然1
超出raise_application_error()
的允许范围。因此,当你来到外部EXCEPTION块时会出现错误。
避免这种情况的方法是删除ERROR_FOUND异常并依赖Oracle的默认异常处理。
在最里面的块中,您想要重新引发除NO_DATA_FOUND之外的任何异常。最简单的方法是删除WHEN OTHERS子句。然后,在外部块中,您将获得可以记录的SQLCODE和SQLERRM的有意义值。然后只需使用RAISE将它们传播到堆栈中....
exception
when others then
rollback;
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);
insert into TA_ERROR_LOG values (v_check,v_table_name,'An error
was encountered '||err_code||':'||err_msg,sysdate);
commit;
raise;
end;
您不仅不会从raise_application_error()
收到错误,您的日志将包含有用的错误编号和消息。
顺便说一句,在EXCEPTION块中使用ROLLBACK和COMMIT是不好的做法。更好的方法是编写一个由AUTONOMOUS_TRANSACTION编译指示覆盖的日志记录过程。这样,日志记录不会干扰更广泛的事务。 Find out more
答案 1 :(得分:1)
传递给raise_application_error过程的错误号必须是-20000 ..- 20999范围内的负整数。
对于用户定义的异常,SQLCODE始终返回+1,因此您将+1作为传递 raise_application_error程序的错误编号,超出范围。
答案 2 :(得分:0)
我已经发布了答案。它可以进一步改进。 pragma exception_init 用于捕获错误(在我的情况下 - Integrity Constraint)。
我已删除了调用'下一个序列值'因为它可以在执行插入之前直接调用。
@APC谢谢:)
CREATE OR REPLACE Procedure HR.insert_TBL_APP is
--declare variables for insert
v_TA_SNO VARCHAR2(10);
v_TA_SEQNO VARCHAR2(6);
v_TA_DESC VARCHAR2(10);
-- Validation
v_check VARCHAR2 (10 Byte);
err_code varchar2(50);
err_msg varchar2(200);
v_table_name varchar2(50):='TBL_APP';
error_found exception;
parent_not_found exception; -- use it to catch the Integrity Constraint
pragma exception_init(parent_not_found, -2291);
cursor c1 is
select distinct TA_SNO,
TA_SEQNO,
TA_DESC
from (
SELECT hdr.FIRST_NO TA_SNO,
-1 TA_SEQNO, -- assign a dummy value as sequence no
hdr.descrip TA_DESC
FROM
FORMS_HDR hdr
WHERE
hdr.seco_name = 'TST121'
union
SELECT hdr.FIRST_NO TA_SNO,
-2 TA_SEQNO, -- assign a dummy value as sequence no
hdr.descrip TA_DESC
FROM
FORMS_HDR hdr
WHERE
hdr.seco_name = 'TST122');
begin
if c1%isopen then
close c1;
end if;
v_check:=null;
FOR i IN c1 LOOP
--assign variables for insert
v_TA_SNO := i.TA_SNO;
v_TA_SEQNO := i.TA_SEQNO;
v_TA_DESC := i.TA_DESC;
begin
--var_TaSeqno := HR.taSeqNoFunc(); --the variable will not be used
select TA_SNO
into v_check
from TBL_APP a
where TA_SNO = i.TA_SNO
and TA_SEQNO =i.TA_SEQNO;
exception
when no_data_found then
Begin -- added line to use exception
--insert into target table
INSERT INTO TBL_APP (TA_SNO,
TA_SEQNO,
TA_DESC
)
values (v_TA_SNO,
TA_SEQNO.nextval, --insert the nextval directly
v_TA_DESC
);
--when the integrity constraint (parent key) error is thrown, insert into the TA_ERROR_LOG
exception
when parent_not_found then
rollback;
err_msg := SUBSTR(SQLERRM, 1, 200);
insert into TA_ERROR_LOG values (v_check,v_table_name, err_msg, sysdate);
commit;
end; -- end begin for using the exception
when others then
raise error_found;
end ;
end loop;
exception when error_found then
rollback;
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);
insert into TA_ERROR_LOG values (v_check,v_table_name, err_msg, sysdate);
commit;
raise_application_error(err_code,err_msg);
end;