oracle - 管理包中异常的最佳方法
问题描述
我有一个包含几个过程和函数的包,这些过程是从外部程序调用的,然后它们又调用函数。
管理异常的最佳方法在哪里?
例如,Prog1 调用 Proc1,Proc1 调用 Funct1,如果在函数中出现异常(“TOO MANY ROW”或“NO DATA FOUND”),这是引发特定自定义消息并立即返回 Prog1 的最佳方式。
在这一刻我有这个
PROCEDURE_1
BEGIN
*code*
CALL FUNCTION_1
*code*
EXCEPTION
WHEN NO DATA FOUND THEN
*print customized message*
RETURN;
END;
FUNCTION_1
BEGIN
*code*
EXCEPTION
WHEN NO DATA FOUND THEN
RAISE;
END;
这是最好的方法吗?
问候, 马可
解决方案
理想情况下,如果发生完全错误,则允许过程失败并出现异常和错误堆栈,但是致命错误和预期条件之间的差异将根据您正在实现的业务逻辑而有所不同,因此很难说应该做什么发生在您的特定情况下。
如果约定的接口是程序应该返回一个格式化的消息,并且该消息可能包括预期的业务条件,例如产品缺货,那么您可以在程序中使用类似这样的东西来处理它(废话伪代码仅用于说明方法):
create or replace procedure procedure_1
( p_result_message out varchar2 )
as
somevar number;
begin
do_stuff('fruit','cake');
begin
somevar := function_1('bananas');
exception
when no_data_found then
p_result_message := 'No kittens are available for this mission.';
return;
end;
p_result_message := 'Cake is available in aisle 3';
exception
when something_else then
p_result_message := 'Self-destruct sequence initiated.';
end;
(对于更纯粹的方法,您可能更喜欢重新排列代码,使其始终以 的值到达末尾p_result_message
,而不是在出现某些情况时中途退出。)
现在,您有一种方法可以处理 中可能合理出现的任何异常function_1
,而无需在函数本身内进行任何特殊处理。
您也可以让函数引发包中定义的异常,尽管这样您就无法在故障点定义诊断错误消息,并且根据我的经验,这只会使事情复杂化。但为了说明:
create or replace package starfleet
as
shield_failure exception;
warp_core_malfunction exception;
pragma exception_init(shield_failure, -20998);
pragma exception_init(warp_core_malfunction, -20999);
procedure check_status
( status_message out varchar2 );
function status
return number;
end starfleet;
create or replace package body starfleet as
function status
return number
is
status_ind number;
begin
select 1 into status_ind from dual where 1=2; -- fails with NDF
return status_ind;
exception
when no_data_found then raise shield_failure;
end status;
procedure check_status
( status_message out varchar2 )
is
status_ind number;
begin
status_ind := status();
status_message := 'Everything is fine';
exception
when warp_core_malfunction then status_message := 'Abandon ship';
when shield_failure then status_message := 'Increase power to shields';
end check_status;
end starfleet;
现在,该status()
函数可以引发包(或任何其他包)中定义的异常,并且过程check_status
可以捕获它并决定如何处理它。
从 SQL*Plus 调用它的示例:
SQL> var status_message varchar2(100)
SQL>
SQL> begin
2 starfleet.check_status(:status_message);
3 end;
4 /
PL/SQL procedure successfully completed.
STATUS_MESSAGE
-------------------------
Increase power to shields
推荐阅读
- azure - ARM 部署:获取 Azure Function API 密钥
- docker - 关于网络接口的 Ansible 未定义事实
- java - 计算递归方法的时间复杂度
- c++ - 选择选举获胜者的程序
- r - 如何使用 ggplot2 将标准错误添加到 nls 图?
- ansible - 如何在 Ansible 中检查某个状态码 (4xx)?
- python - Python - 替换列表中的特定数字
- javascript - 无法将json数据获取到jquery数据表
- javascript - 如何在 element 的 slideUp() 之前阻止滚动和 body 的高度,并在新元素的 slideDown() 之后删除 css?- jQuery
- excel - VBA Shell()、WSrcipt.Shell 和 Shell.Application。我还能尝试什么?