SQL: 函数中的异常处理
SQL: exception handling in a function
今天遇到一个比较玄乎的问题。当我使用以下参数执行我的 SQL 函数 f_interestrate()
(当其中一个参数等于 0 时,它应该引发我定义的异常):
SELECT GENERAL_FUNCTIONS.F_INTERESTRATE(2500000, 0.10, 0) FROM dual;
给我以下错误:
ORA-06503: PL/SQL: Function returned without value
ORA-06512: at "NOAHBASE.GENERAL_FUNCTIONS", line 73
06503. 00000 - "PL/SQL: Function returned without value"
*Cause: A call to PL/SQL function completed, but no RETURN statement was executed.
*Action: Rewrite PL/SQL function, making sure that it always returns
a value of a proper type.
但是正如您在下面的代码示例中看到的那样,该函数应该引发我定义的异常 ex_invalid_devisor
。不要忘记提到这个函数嵌套在一个包中。
FUNCTION f_interestrate(pn_principal NUMBER, pn_interest NUMBER, pn_years NUMBER) RETURN NUMBER IS
vn_interestrate NUMBER;
ex_invalid_devisor EXCEPTION;
BEGIN
IF pn_principal = 0 OR
pn_interest = 0 OR
pn_years = 0 THEN
RAISE ex_invalid_devisor;
ELSE
vn_interestrate := ((pn_interest/pn_principal)-1)/pn_years;
RETURN vn_interestrate;
END IF;
EXCEPTION
WHEN ex_invalid_devisor THEN
DBMS_OUTPUT.PUT_LINE('Devisor must be bigger then 0');
END;
我做错了什么吗?
这就是您应该如何处理...我在您的代码中添加了 'return -1'。 HTH.
create or replace FUNCTION f_interestrate(pn_principal NUMBER, pn_interest NUMBER, pn_years NUMBER) RETURN NUMBER IS
vn_interestrate NUMBER;
ex_invalid_devisor EXCEPTION;
BEGIN
IF pn_principal = 0 OR
pn_interest = 0 OR
pn_years = 0 THEN
RAISE ex_invalid_devisor;
ELSE
vn_interestrate := ((pn_interest/pn_principal)-1)/pn_years;
RETURN vn_interestrate;
END IF;
EXCEPTION
WHEN ex_invalid_devisor THEN
DBMS_OUTPUT.PUT_LINE('Devisor must be bigger then 0');
return -1;
END;
SQL> select F_INTERESTRATE(2500000, 0.10, 0) FROM dual;
F_INTERESTRATE(2500000,0.10,0)
------------------------------
-1
因为 PL/SQL 已经有一个非常好的 zero_divide
异常,我很想把函数写成:
create or replace function f_interestrate
( pn_principal number
, pn_interest number
, pn_years number )
return number
as
begin
return ((pn_interest / pn_principal) - 1) / pn_years;
end;
然后您将收到默认的失败消息:
SQL> select f_interestrate(2500000, 0.10, 0) from dual;
select f_interestrate(2500000, 0.10, 0) from dual
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at "XXX.F_INTERESTRATE", line 8
或者如果你真的需要一些定制处理,
create or replace function f_interestrate
( pn_principal number
, pn_interest number
, pn_years number )
return number
as
begin
return ((pn_interest / pn_principal) - 1) / pn_years;
exception
when zero_divide then
[[[ do something here ]]]
end;
我注意到您在 pn_interest
为零时也引发了自定义 ex_invalid_devisor
异常,即使它没有用作除数,所以我可能在这里缺少一些微妙的逻辑。
(编辑:考虑一下,如果 pn_interest
为零,那么也许您只需要 return pn_principal
即可。)
今天遇到一个比较玄乎的问题。当我使用以下参数执行我的 SQL 函数 f_interestrate()
(当其中一个参数等于 0 时,它应该引发我定义的异常):
SELECT GENERAL_FUNCTIONS.F_INTERESTRATE(2500000, 0.10, 0) FROM dual;
给我以下错误:
ORA-06503: PL/SQL: Function returned without value
ORA-06512: at "NOAHBASE.GENERAL_FUNCTIONS", line 73
06503. 00000 - "PL/SQL: Function returned without value"
*Cause: A call to PL/SQL function completed, but no RETURN statement was executed.
*Action: Rewrite PL/SQL function, making sure that it always returns a value of a proper type.
但是正如您在下面的代码示例中看到的那样,该函数应该引发我定义的异常 ex_invalid_devisor
。不要忘记提到这个函数嵌套在一个包中。
FUNCTION f_interestrate(pn_principal NUMBER, pn_interest NUMBER, pn_years NUMBER) RETURN NUMBER IS
vn_interestrate NUMBER;
ex_invalid_devisor EXCEPTION;
BEGIN
IF pn_principal = 0 OR
pn_interest = 0 OR
pn_years = 0 THEN
RAISE ex_invalid_devisor;
ELSE
vn_interestrate := ((pn_interest/pn_principal)-1)/pn_years;
RETURN vn_interestrate;
END IF;
EXCEPTION
WHEN ex_invalid_devisor THEN
DBMS_OUTPUT.PUT_LINE('Devisor must be bigger then 0');
END;
我做错了什么吗?
这就是您应该如何处理...我在您的代码中添加了 'return -1'。 HTH.
create or replace FUNCTION f_interestrate(pn_principal NUMBER, pn_interest NUMBER, pn_years NUMBER) RETURN NUMBER IS
vn_interestrate NUMBER;
ex_invalid_devisor EXCEPTION;
BEGIN
IF pn_principal = 0 OR
pn_interest = 0 OR
pn_years = 0 THEN
RAISE ex_invalid_devisor;
ELSE
vn_interestrate := ((pn_interest/pn_principal)-1)/pn_years;
RETURN vn_interestrate;
END IF;
EXCEPTION
WHEN ex_invalid_devisor THEN
DBMS_OUTPUT.PUT_LINE('Devisor must be bigger then 0');
return -1;
END;
SQL> select F_INTERESTRATE(2500000, 0.10, 0) FROM dual;
F_INTERESTRATE(2500000,0.10,0)
------------------------------
-1
因为 PL/SQL 已经有一个非常好的 zero_divide
异常,我很想把函数写成:
create or replace function f_interestrate
( pn_principal number
, pn_interest number
, pn_years number )
return number
as
begin
return ((pn_interest / pn_principal) - 1) / pn_years;
end;
然后您将收到默认的失败消息:
SQL> select f_interestrate(2500000, 0.10, 0) from dual;
select f_interestrate(2500000, 0.10, 0) from dual
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at "XXX.F_INTERESTRATE", line 8
或者如果你真的需要一些定制处理,
create or replace function f_interestrate
( pn_principal number
, pn_interest number
, pn_years number )
return number
as
begin
return ((pn_interest / pn_principal) - 1) / pn_years;
exception
when zero_divide then
[[[ do something here ]]]
end;
我注意到您在 pn_interest
为零时也引发了自定义 ex_invalid_devisor
异常,即使它没有用作除数,所以我可能在这里缺少一些微妙的逻辑。
(编辑:考虑一下,如果 pn_interest
为零,那么也许您只需要 return pn_principal
即可。)