我有多个存储过程在我的数据库中调用多个存储过程。举一个小例子,我在下面构建了一些虚构的版本。在我的示例中,Java程序调用{{1}},调用calculate_bill
,调用calculate_commission
。
我希望得到一些关于如何最好地将错误消息从堆栈传播到调用Java层的建议,以便用户获得与错误发生位置相对应的精确错误消息。
我真的很坚持这个。我在update_record
的示例中玩过,并且不断地将它拖到堆栈中。我在下面的方式是远程正确吗?或者在相关程序中是否有一个raise_application_error,不需要raise_application_error
等?
为了明白我的意思,在下面的例子中,如果用户输入的数字对应于由于不存在而无法更新的记录,我希望他们得到消息: “计算账单时出错。计算佣金时出错。没有记录需要更新”或其他相关内容。
所以有两个问题:
实施例: (代码错误):
pragma exception init
Java代码:
-20000 : Error in top level procedure
-20001 : Error in middle level procedure
-20002 : Error in bottom level procedure
Oracle代码:
try {
// call calculate_bill
exception (SQLException ex)
// output oracle code and relevant message.
注意:我知道这个例子有点做作。我只是想保持简短。
答案 0 :(得分:3)
我实现这个的方法是使用RAISE_APPLICATION_ERROR
实际发生错误的地方,然后在其他层中保持未处理(或者,如果你想在数据库中登录,请在{{{ 1}}部分,然后使用OTHERS
而不是RAISE
重新加注。
您RAISE_APPLICATION_ERROR
个部分仍然存在上一个问题中出现的问题:当发生未知错误时,您将用一般的,无用的消息替换它。要解释Tom Kyte,“未在OTHERS
中结束的WHEN OTHERS
是一个错误。”
如果没有登录数据库,我会重新编写提供的代码,如下所示:
RAISE
下面是示例输入及其创建的堆栈跟踪:
create or replace procedure calculate_bill(in_num NUMBER)
is
begin
if in_num > 2 then
calculate_commission(in_num);
else
raise_application_error(-20000, 'Error calculating bill. ' || 'Record number doesn''t exist.', false);
end if;
end;
create or replace procedure calculate_commission(in_num NUMBER)
is
begin
if in_num < 30 then
raise_application_error(-20001, 'Number too small to calculate commission.', false);
elsif in_num >= 30 and in_num < 40 then
update_record(in_num);
else
raise_application_error(-20001, 'Number too large to calculate commission', false);
end if;
end;
create or replace procedure update_record(in_num NUMBER)
is
v_stub number;
begin
select 1 into v_stub from dual where 1 = 0;
exception
when no_data_found then
raise_application_error(-20002, 'No record exists to be updated', false);
end;
如果您要将错误记录添加到这些过程,那么向exec calculate_bill(0)
ORA-20000: Error calculating bill. Record number doesn't exist.
ORA-06512: at "SCHEMANAME.CALCULATE_BILL", line 7
ORA-06512: at line 1
exec calculate_bill(10)
ORA-20001: Number too small to calculate commission.
ORA-06512: at "SCHEMANAME.CALCULATE_COMMISSION", line 5
ORA-06512: at "SCHEMANAME.CALCULATE_BILL", line 5
ORA-06512: at line 1
exec calculate_bill(35)
ORA-20002: No record exists to be updated
ORA-06512: at "SCHEMANAME.UPDATE_RECORD", line 8
ORA-06512: at "SCHEMANAME.CALCULATE_COMMISSION", line 7
ORA-06512: at "SCHEMANAME.CALCULATE_BILL", line 5
ORA-06512: at line 1
exec calculate_bill(100)
ORA-20001: Number too large to calculate commission
ORA-06512: at "SCHEMANAME.CALCULATE_COMMISSION", line 9
ORA-06512: at "SCHEMANAME.CALCULATE_BILL", line 5
ORA-06512: at line 1
部分添加OTHERS
子句就很简单了:
EXCEPTION
WHEN OTHERS THEN
my_logging (SQLCODE, SQLERRM, DBMS_UTILITY.format_error_backtrace ());
RAISE;
调用创建的新例外将由RAISE_APPLICATION_ERROR
透明处理。