PL/SQL中的异常处理

异常是指中断正常程序指令流的错误。PL/SQL为我们提供了引发异常的异常块,从而帮助程序员找出故障并解决它。

null

PL/SQL中定义了两种类型的异常

  1. 用户定义的异常。
  2. 系统定义的异常。

编写异常的语法

WHEN exception THEN 
    statement;

声明 申报科;

开始 可执行命令;

例外 那么什么时候例外 声明1; 那么什么时候例外 声明2; [当其他人那时] /*默认异常处理代码*/

终止

注: 当其他人 关键字只应在异常处理块的末尾使用,因为稍后出现的异常处理部分不会被执行,因为控件将在执行其他部分后退出该块。

  1. 系统定义的例外情况:
  2. 这些异常是在PL/SQL中预定义的,当确定 违反了数据库规则。 系统定义的例外情况进一步分为两类:

    1. 命名系统异常。
    2. 未命名的系统异常。

  • 命名系统异常:它们有一个系统预先定义的名称,比如ACCESS_INTO_NULL、DUP_VAL_ON_INDEX、LOGIN_DENIED等。列表非常大。

    因此,我们将讨论一些最常用的例外情况:

    让我们来创建一个表格。

    create table geeks(g_id int , g_name varchar(20), marks int); 
    insert into geeks values(1, 'Suraj',100);
    insert into geeks values(2, 'Praveen',97);
    insert into geeks values(3, 'Jessie', 99);
    

    图片[1]-PL/SQL中的异常处理-yiteyi-C++库

    1. 找不到数据 :返回SELECT INTO语句时引发 排。例如:

      DECLARE
      temp varchar (20);
      BEGIN
      SELECT g_id into temp from geeks where g_name= 'GeeksforGeeks' ;
      exception
      WHEN no_data_found THEN
      dbms_output.put_line( 'ERROR' );
      dbms_output.put_line( 'there is no name as' );
      dbms_output.put_line( 'GeeksforGeeks in geeks table' );
      end ;

      
      

      输出:

      ERROR
      there is no name as GeeksforGeeks in geeks table
      
    2. 太多行了 :返回SELECT INTO语句时引发 更多 不止一排。

      DECLARE
      temp varchar (20);
      BEGIN
      -- raises an exception as SELECT
      -- into trying to return too many rows
      SELECT g_name into temp from geeks;
      dbms_output.put_line( temp );
      EXCEPTION
      WHEN too_many_rows THEN
      dbms_output.put_line( 'error trying to SELECT too many rows' );
      end ;

      
      

      输出:

      error trying to SELECT too many rows
      
    3. 值错误 :执行导致算术、数字、字符串、转换或约束错误的语句时,会引发此错误。此错误主要由程序员错误或无效数据输入引起。

      DECLARE
      temp number;
      BEGIN
      SELECT g_name into temp from geeks where g_name= 'Suraj' ;
      dbms_output.put_line( 'the g_name is ' || temp );
      EXCEPTION
      WHEN value_error THEN
      dbms_output.put_line( 'Error' );
      dbms_output.put_line( 'Change data type of temp to varchar(20)' );
      END ;

      
      

      输出:

      Error
      Change data type of temp to varchar(20)
      
    4. 零分 =用零除时引发异常。

      DECLARE
      a int :=10;
      b int :=0;
      answer int ;
      BEGIN
      answer:=a/b;
      dbms_output.put_line( 'the result after division is' ||answer);
      exception
      WHEN zero_divide THEN
      dbms_output.put_line( 'dividing by zero please check the values again' );
      dbms_output.put_line( 'the value of a is ' ||a);
      dbms_output.put_line( 'the value of b is ' ||b);
      END ;

      
      

      输出:

      dividing by zero please check the values again
      the value of a is 10
      the value of b is 0
      

  • 未命名的系统异常:Oracle没有为一些被称为未命名系统异常的系统异常提供名称。这些例外 不要 经常发生。这些例外有两部分 代码和相关消息 . 处理这些异常的方法是 指定名称 使用 Pragma异常_INIT 语法:
    PRAGMA EXCEPTION_INIT(exception_name, -error_number);
    

    错误号是预定义的,其负整数范围为-20000到-20999。

    例子:

    DECLARE
    exp exception;
    pragma exception_init (exp, -20015);
    n int :=10;
    BEGIN
    FOR i IN 1..n LOOP
    dbms_output.put_line(i*i);
    IF i*i=36 THEN
    RAISE exp;
    END IF;
    END LOOP;
    EXCEPTION
    WHEN exp THEN
    dbms_output.put_line( 'Welcome to GeeksforGeeks' );
    END ;

    
    

    输出:

    1
    4
    9
    16
    25
    36
    Welcome to GeeksforGeeks
    

  • 用户定义的例外情况: 这类用户可以根据需要创建自己的异常,并明确提出这些异常 提升 命令被使用。

    例子:

    • 将非负整数x除以y,使结果大于或等于1。

      从给定的问题我们可以得出结论,存在两个例外

      • 除法为零。
      • 如果结果大于或等于1,则表示y小于或等于x。

      DECLARE
      x int :=&x; /*taking value at run time */
      y int :=&y;
      div_r float ;
      exp1 EXCEPTION;
      exp2 EXCEPTION;
      BEGIN
      IF y=0 then
      raise exp1;
      ELSEIF y > x then
      raise exp2;
      ELSE
      div_r:= x / y;
      dbms_output.put_line( 'the result is ' ||div_r);
      END IF;
      EXCEPTION
      WHEN exp1 THEN
      dbms_output.put_line( 'Error' );
      dbms_output.put_line( 'division by zero not allowed' );
      WHEN exp2 THEN
      dbms_output.put_line( 'Error' );
      dbms_output.put_line( 'y is greater than x please check the input' );
      END ;

      
      

      Input 1: x = 20
               y = 10
      
      Output: the result is 2
      
      Input 2: x = 20
               y = 0
      
      Output:
      Error
      division by zero not allowed
      
      Input 3: x=20
               y = 30
      
      Output:<.em>
      Error
      y is greater than x please check the input
      

    引发应用程序错误 : 它用于显示用户定义的错误消息,错误号的范围在-20000到-20999之间。当RAISE_应用程序_ERROR执行时,它返回错误消息和错误代码,看起来 与Oracle内置错误相同。

    例子:

    DECLARE
    myex EXCEPTION;
    n NUMBER :=10;
    BEGIN
    FOR i IN 1..n LOOP
    dbms_output.put_line(i*i);
    IF i*i=36 THEN
    RAISE myex;
    END IF;
    END LOOP;
    EXCEPTION
    WHEN myex THEN
    RAISE_APPLICATION_ERROR(-20015, 'Welcome to GeeksForGeeks' );
    END ;

    
    

    输出:

    Error report:
    ORA-20015: Welcome to GeeksForGeeks
    ORA-06512: at line 13
    
    1
    4
    9
    16
    25
    36
    
    
    

    注: 该输出基于Oracle Sql developer 顺序 如果您在其他地方运行此代码,可能会发生更改。

    异常处理中的作用域规则 :

    1. 我们不能两次声明异常,但我们可以声明 相同的 例外情况 两个不同的街区。
    2. 块内声明的异常是 地方的 去那个街区 全球的 到它的所有子块。

    由于块只能引用局部或全局异常,所以封闭块不能引用子块中声明的异常。 如果我们在子块中重新声明全局异常,则以局部声明为准,即局部的范围更大。

    例子:

    DECLARE
    GeeksforGeeks EXCEPTION;
    age NUMBER:=16;
    BEGIN
    --  sub-block BEGINs
    DECLARE
    -- this declaration prevails
    GeeksforGeeks  EXCEPTION;
    age NUMBER:=22;
    BEGIN
    IF age > 16 THEN
    RAISE GeeksforGeeks; /* this is not handled*/
    END IF;
    END ;
    -- sub-block ends
    EXCEPTION
    -- Does not handle raised exception
    WHEN GeeksforGeeks THEN
    DBMS_OUTPUT.PUT_LINE
    ( 'Handling  GeeksforGeeks exception.' );
    WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE
    ( 'Could not recognize exception GeeksforGeeks  in this scope.' );
    END ;

    
    

    输出:

    Could not recognize exception GeeksforGeeks  in this scope.
    

    优势:

    • 异常处理对于错误处理非常有用,如果没有异常处理,我们必须在每个点发出命令来检查执行错误: 例子:
      Select ..
      .. check for 'no data found' error
      Select ..
      .. check for 'no data found' error
      Select .. 
      .. check for 'no data found' error
      

      在这里我们可以看到它不是 强健的 由于错误处理与正常处理是不分开的,如果我们遗漏了代码中的某一行,它可能会导致其他类型的错误。

    • 通过异常处理,我们可以在不多次编写语句的情况下处理错误,甚至可以处理 不同的 一个异常块中的错误类型: 例子:
      BEGIN
         SELECT ...
         SELECT ...
         SELECT ...
          .
          .
          .
      exception 
         WHEN NO_DATA_FOUND THEN  /* catches all 'no data found' errors */
           ...
         WHEN ZERO_DIVIDE THEN    /* different types of */
         WHEN value_error THEN    /* errors handled in same block */
         ...   
       

    从上面的代码中,我们可以得出以下结论:异常处理

    1. 改善 可读性 通过让我们隔离错误处理例程,从而提供健壮性。
    2. 提供 可靠性 ,而不是在每个点检查不同类型的错误,我们可以简单地将它们写入异常块,如果存在错误,将引发异常,从而帮助程序员找出错误类型并最终解决它。

    使用 :exception在现实生活中的一个用法可以在在线列车预订系统中找到。 在填写车站代码预订车票时,如果我们输入了错误的代码,它会向我们显示数据库中不存在该代码的例外情况。

    参考: 您可以在这里找到所有预定义异常的列表。 预定义异常的总数

  • © 版权声明
    THE END
    喜欢就支持一下吧
    点赞14 分享