在 oracle 中一次捕获多个异常

Posted

技术标签:

【中文标题】在 oracle 中一次捕获多个异常【英文标题】:Catching multiple exception at once in oracle 【发布时间】:2020-02-06 12:27:50 【问题描述】:

请告诉我是否可以在 oracle 中同时捕获多个异常。不像 1 个用户定义和 1 个是 oracle 默认值。我需要同时捕获多个用户定义的异常。请告诉我该怎么做。

谢谢!

【问题讨论】:

能否提供您用于同时导致多个异常的代码? 我不明白这怎么可能。你执行一个操作。它会产生异常。你捕捉到了异常。唯一可能的额外异常将来自您在处理第一个异常时所做的事情。这并不是说您可以生成异常但忽略它们并继续处理,然后最后返回并收集您忽略的所有异常。 你的意思是bulk exception handling?还是DML Error Logging?如果这些都不能解决您的问题,您需要编辑您的问题,以提供有关您想要实现的目标的更多详细信息。 另一种选择,你的意思是单个代码单元可能会抛出几个异常中的一个,而你的异常块需要捕获并处理抛出的任何一个? 【参考方案1】:

当然,如果我正确理解了这个问题的话。它被称为WHEN OTHERS。不过,人们通常误用它,尤其是在使用时

exception
  when others then 
    null;
end;

因为它成功隐藏了可能出现的任何错误。 WHEN OTHERS 在开发过程中是可以的,但在生产过程中可能真的很糟糕,特别是如果它不包含 raise

【讨论】:

【参考方案2】:

是的,您可以按照@Littlefoot 或批量处理错误(此处未涵盖)指示的“当其他人”执行您想要的操作。但另外,您可以在 WHEN 上有一个 OR 条件异常名称子句。它不是很有用,因为通常需要更多代码来 2 个单独的 WHEN 条件,但它是有效的语法。下面演示各种错误定义方法和异常处理。

create table except_demo ( id integer, col1 varchar2(20));
insert into except_demo (id, col1)
  select 5,'OK' from dual union all
  select 6,'Too Many' from dual union all 
  select 6,'Still' from dual;

select id, count(*) from except_demo group by id;

create or replace procedure catcher(which_in integer, select_in boolean default False)
is
  e_user_1 exception; 
  e_user_2 exception; 
  invalid_which_range exception;  
  appErr_inactive_acct exception;
  sample_ora_error exception;
  pragma exception_init (sample_ora_error, -00060);

  rae exception;
  rae_num constant integer := -20100;
  pragma exception_init  (rae, -20100);  

  col1_value except_demo.col1%type; 
begin
   dbms_output.put( 'Enter catcher(' || which_in || ') Result=>');
   if which_in > 8 
      then raise invalid_which_range;
   end if ;
   if select_in 
   then 
       select col1 
         into col1_value
         from except_demo
        where id = which_in;
        dbms_output.put_line('Select Successful 1 row selected.');         
   else 
       case which_in
            when 1 then raise e_user_1;
            when 2 then raise e_user_2;
            when 3 then raise appErr_inactive_acct;
            when 4 then raise sample_ora_error;
            else raise_application_error(rae_num, 'Which_In=' || which_in || ' invalid. Please specify number 1-7 only'); 
        end case;
    end if; 
exception 
   when e_user_1         
   then dbms_output.put_line('Error e_user_1');    -- user error

   when e_user_2         
   then dbms_output.put_line('Error e_user_2');

   when no_data_found or too_many_rows        
   then dbms_output.put_line('Select except_demo where id=' || which_in ||'; Returned 0 or more than 1 row. Must return exactly 1.' );    -- oracle predefined error

   when sample_ora_error           
   then dbms_output.put_line('Ora Error:: ' || sqlerrm );            -- oracle error NOT predefined 

   when appErr_inactive_acct 
   then dbms_output.put_line('Error Account id ' || which_in || ' is inactive.');  -- user error

   when rae 
   then dbms_output.put_line(sqlerrm); 

end catcher; 

declare 
  do_select boolean; 
begin 
    for i in 1..9
    loop
       do_select := (i between 5 and 7);
       catcher(i,do_select);
    end loop;
exception 
    when others 
    then 
        dbms_output.put_line('Error returned from catcher=>' || sqlerrm);
        raise; 
end ;  


drop procedure catcher;
drop table except_demo; 

在实时环境中,dbms_output 语句将被替换,将消息和其他信息写入异常日志表,而不是 dbms_output。

我和 Littlefoot 有一点小分歧。我坚信在开发中编写的任何东西,无论是否有意,都会在生产中运行。很多时候,让你陷入困境的是意外。因此,误用 WHEN OTHERS 的示例即使在开发中也无效

【讨论】:

以上是关于在 oracle 中一次捕获多个异常的主要内容,如果未能解决你的问题,请参考以下文章

oracle plsql 捕获异常和抛出异常

请教各位高手 oracle 存储过程 如何获得 捕获异常的内容

oracle存储过程异常捕获

捕获多个异常-C# [重复]

java7 异常处理增强

C# 中如何一次 catch 多个异常?