将函数分配给变量并在过程中使用它
Assign function to a variable and use it within procedure
我在过程中使用 'Next Sequence Values' 时遇到问题。
我有 'external' 函数来 return 序列的下一个值。
在我的程序中,我想将该序列的值分配给一个变量
并在我的光标中使用该变量(因为我在我的光标中使用联合语句)。
但它不起作用。
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: error number argument to raise_application_error of 1 is out of range"
请帮助我。谢谢。
您传递给 raise_application_error 过程的错误编号必须是 -20000..-20999 范围内的负整数。
对于用户定义的异常 SQLCODE returns 始终 +1,因此您将 +1 传递为
raise_application_error 过程的错误编号,超出范围。
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 pragma 中的日志程序。这样日志记录就不会干扰更广泛的事务。 Find out more.
我已经发布了答案。它可以进一步改进。
pragma exception_init 用于捕获错误(在我的例子中 - 完整性约束)。
我删除了调用 'next sequence value' 的函数,因为它可以在执行插入之前直接调用。
@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;
我在过程中使用 'Next Sequence Values' 时遇到问题。
我有 'external' 函数来 return 序列的下一个值。 在我的程序中,我想将该序列的值分配给一个变量 并在我的光标中使用该变量(因为我在我的光标中使用联合语句)。
但它不起作用。
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: error number argument to raise_application_error of 1 is out of range"
请帮助我。谢谢。
您传递给 raise_application_error 过程的错误编号必须是 -20000..-20999 范围内的负整数。
对于用户定义的异常 SQLCODE returns 始终 +1,因此您将 +1 传递为 raise_application_error 过程的错误编号,超出范围。
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 pragma 中的日志程序。这样日志记录就不会干扰更广泛的事务。 Find out more.
我已经发布了答案。它可以进一步改进。 pragma exception_init 用于捕获错误(在我的例子中 - 完整性约束)。
我删除了调用 'next sequence value' 的函数,因为它可以在执行插入之前直接调用。
@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;