`

PL/SQL Exception Example

 
阅读更多

一个PL/SQL程序的错误可以分为两种:编译时刻错误、运行时刻错误。

 

编译时刻错误

由于用户输入(如表名拼写错误)、能力(语法格式错误)等方面的原因而造成的程序方面的错误就是编译时的错误。这些错误在编译时会被PL/SQL编译器发现。也可以查询数据字典USER_ERRORS、ALL_ERRORS、DBA_ERRORS来读取错误信息。

 

运行时刻错误

即便是通过了编译的PL/SQL程序在运行时刻还是可能产生错误的。导致运行时错误的原因很多,如内存用尽、硬件故障、违反表的完整性约束、设计上的缺陷、被0除、数字或值在长度大小方面不匹配等。

 

在程序内部不需要对编译时错误做特殊处理。而运行时错误可能随着运行环境的变化而随时出现,难以预防、检查、排除。所以为了提高程序的健壮性、处理潜在的错误,开发人员必须在程序中尽可能地考虑各种主要异常错误,并进行相应的处理。

 

异常分为系统预定义、非预定义、用户定义三种。另外,异常分为错误和非错误两种。系统预定义、非预定义的异常都是针对Oracle(发现的)错误的,而用户定义的异常一般用于处理非错误的异常。

 

 

预定义异常错误

可以查看${ORACLE_HOME}\RDBMS\ADMIN\stdspec.sql脚本文件可以找到这些预定义异常错误。

预定义异常错误虽然是被隐含引发的,但要在异常处理部分利用“异常处理名称”来处理相应的异常错误。

 

--NO_DATA_FOUND

DECLARE
   v_ename   emp.ename%TYPE;
   v_empno   emp.empno%TYPE;
BEGIN
   v_empno := &eno;

   SELECT ename
     INTO v_ename
     FROM emp
    WHERE empno = v_empno;

   DBMS_OUTPUT.put_line (
      '雇员编号:' || v_empno || ',雇员名称:' || v_ename);
EXCEPTION
   WHEN NO_DATA_FOUND
   THEN
      DBMS_OUTPUT.put_line (
         '雇员编号:' || v_empno || ',不存在,请重新输入');
END;
/

 

--CASE_NOT_FOUND

DECLARE
   v_grade   CHAR := 'D';
BEGIN
   CASE v_grade
      WHEN 'A'
      THEN
         DBMS_OUTPUT.put_line ('Excellent');
      WHEN 'B'
      THEN
         DBMS_OUTPUT.put_line ('Very good');
      WHEN 'C'
      THEN
         DBMS_OUTPUT.put_line ('Good');
   END CASE;
EXCEPTION
   WHEN case_not_found
   THEN
      DBMS_OUTPUT.put_line ('No such grade');
      DBMS_OUTPUT.put_line (
         '在CASE语句中缺少与 ' || 'D' || ' 相关的条件');
END;
/
 

--DUP_VAL_ON_INDEX

DECLARE
   v_dept   dept%ROWTYPE;
BEGIN
   INSERT INTO dept
        VALUES (40, '印刷厂', '北京海淀区');
EXCEPTION
   WHEN DUP_VAL_ON_INDEX
   THEN
      DBMS_OUTPUT.put_line (
         '违反了主键(部门编号)不能重复的实体完整性约束');
END;
/
 

--TOO_MANY_ROWS

DECLARE
   v_ename   emp.ename%TYPE;
BEGIN
   SELECT ename
     INTO v_ename
     FROM emp
    WHERE sal = &sal;
EXCEPTION
   WHEN TOO_MANY_ROWS
   THEN
      DBMS_OUTPUT.put_line (
         '返回了多行,请使用游标来处理多行记录的集合');
END;
/
 

--OTHERS

BEGIN
   DBMS_OUTPUT.put_line (1 / 0);                            --会发生ZERO_DIVIDE异常
EXCEPTION
   WHEN DUP_VAL_ON_INDEX
   THEN
      DBMS_OUTPUT.put_line (
         '违反了主键(部门编号)不能重复的实体完整性约束');
   WHEN TOO_MANY_ROWS
   THEN
      DBMS_OUTPUT.put_line (
         '返回了多行,请使用游标来处理多行记录的集合');
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line ('发生了其他异常');
END;
/

 

非预定义异常错误

--为错误代码为“-1400”的Oracle错误声明异常,并进行处理

DECLARE
   ept_null_error   EXCEPTION;
   PRAGMA EXCEPTION_INIT (ept_null_error, -1400);
BEGIN
   INSERT INTO dept
        VALUES (NULL, '印刷厂', '北京海淀区');
EXCEPTION
   WHEN ept_null_error
   THEN
      DBMS_OUTPUT.put_line ('不能向dept表的"部门编号"列插入NULL');
END;
/

 

自定义异常

预定义异常、非预定义异常都是有Oracle判断的异常错误。而在实际的PL/SQL程序开发过程中,为了实施具体的业务规则、编程和调试的需要,程序员可以自定义一些异常。他们往往并不一定是个错误,也不会对数据库造成破坏性的影响,而是程序员为特殊情况所定义的异常,以便将程序的控制流程引向异常处理部分,利用异常处理部分来集中处理这些问题。这种方法使程序的结果比较完美。

自定义异常必须要声明,并且必须要用RAISE语句显示引发(或抛出),然后才能将程序的控制流程引向异常处理部分。

 

--用异常处理的方法来补充提示雇员的工资太高了

DECLARE
   v_empno   emp.empno%TYPE;
   v_sal     emp.sal%TYPE;
   ept_sal   EXCEPTION;
BEGIN
   v_empno := &eno;

   SELECT sal
     INTO v_sal
     FROM emp
    WHERE empno = v_empno;

   IF v_sal >= 4000
   THEN
      DBMS_OUTPUT.put_line (v_empno || ' 雇员的工资是 ' || v_sal);
      RAISE ept_sal;
   ELSE
      DBMS_OUTPUT.put_line (
         v_empno || ' 雇员的工资是 ' || v_sal || ',基本正常');
   END IF;
EXCEPTION
   WHEN ept_sal
   THEN
      DBMS_OUTPUT.put_line (
         '补充:该雇员的工资超过4000了,太高了');
END;
/
 

使用SQLCODE和SQLERRM

另一种处理异常(预定义、尤其是非预定义异常)的方法是在异常处理部分最后的WHEN OTHERS子句使用内置异常函数SQLCODE和SQLERRM,以便根据SQL语句执行后的状态,即错误代码和错误消息,决定处理方法。

SQLCODE函数没有参数,它返回Oracle的错误代码的数字。

SQLERRM(oracle_error_code)函数按照输入的Oracle错误代码oracle_error_code返回其对应的Oracle错误消息文本。当省略oracle_error_code时,SQLERRM函数返回SQLCODE当前值对应的错误消息文本。

 

--几个特殊错误代码时SQLERRM函数的返回值

BEGIN
   DBMS_OUTPUT.put_line ('SQLERRM(0): ' || SQLERRM (0));
   DBMS_OUTPUT.put_line ('SQLERRM(100): ' || SQLERRM (100));
   DBMS_OUTPUT.put_line ('SQLERRM(10): ' || SQLERRM (10));
   DBMS_OUTPUT.put_line ('SQLERRM(1): ' || SQLERRM (1));
   DBMS_OUTPUT.put_line ('SQLERRM: ' || SQLERRM);
   DBMS_OUTPUT.put_line ('SQLERRM(-1): ' || SQLERRM (-1));
   DBMS_OUTPUT.put_line ('SQLERRM(-54): ' || SQLERRM (-54));
END;
/

SQLCODE和SQLERRM函数均不能直接用在SQL语句中,如果需要在SQL语句中使用的话,需要先将其值赋予变量,然后再引用。

 

--用SQLCODE和SQLERRM函数来处理非预定义异常错误

BEGIN
   INSERT INTO dept
        VALUES (NULL, '印刷厂', '北京海淀区');
EXCEPTION
   WHEN NO_DATA_FOUND
   THEN
      DBMS_OUTPUT.put_line ('没有找到数据');
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line (SQLCODE || '、' || SQLERRM);

      CASE SQLCODE
         WHEN -1400
         THEN
            DBMS_OUTPUT.put_line ('不能向非空字段插入NULL值');
         WHEN -2291
         THEN
            DBMS_OUTPUT.put_line ('主表中没有主键值,不能更新');
         WHEN -2292
         THEN
            DBMS_OUTPUT.put_line ('还有子记录,不能删除父记录');
      END CASE;
END;
/
 

 

 

 

 

分享到:
评论

相关推荐

    Oracle PL/SQL by Example(4th Edition)

    《Oracle PL/SQL by Example(4th Edition)》是一本专为Oracle数据库用户设计的PL/SQL编程指南,尤其适合那些希望通过实践学习这一强大的过程式语言的开发者。本书的第四版详细介绍了Oracle PL/SQL的各种核心概念和...

    Oracle PL/SQL实例编程(PL/SQL经典书籍)

    5. **异常处理**:PL/SQL提供了异常处理机制,通过BEGIN...EXCEPTION块来捕获和处理运行时错误,如NO_DATA_FOUND、TOO_MANY_ROWS和OTHERS。 6. **包(PACKAGE)**:包是将相关的常量、变量、过程和函数组合在一起的...

    PL.SQL.By.Example

    《PL.SQL by Example》是一本专注于Oracle数据库PL/SQL编程实践的资源,它提供了一系列的实例脚本,旨在帮助读者深入理解和掌握PL/SQL语言。PL/SQL是Oracle数据库系统中的一个关键组件,用于开发存储过程、触发器、...

    Oracle PL_SQL by Example 4th.Edition.Aug.2008

    2. **控制结构**:PL/SQL的流程控制是其强大之处,书中详细讨论了循环(WHILE、FOR)、条件判断(IF-THEN-ELSIF、CASE)以及异常处理(BEGIN-EXCEPTION-END)等结构,使读者能够编写出逻辑清晰的代码。 3. **游标**...

    oracle_pl_sql_by_example_4th_edition

    《Oracle PL/SQL by Example, 4th Edition》是一本专为Oracle数据库用户和开发者编写的PL/SQL编程指南。这本书深入浅出地介绍了Oracle的PL/SQL编程语言,是学习和提升PL/SQL技能的重要参考资料。PL/SQL是Oracle...

    PL:Sql script .zip_sql

    描述中的"example pl sql script"指出这是一个示例PL/SQL脚本。这可能是一个教学或演示用的代码,用于展示如何在PL/SQL环境中编写和执行各种操作,如数据查询、事务处理、存储过程、函数、触发器等。 标签"sql...

    plsqldev12.0.4.1826x64主程序+ v12中文包+keygen

    The new PL/SQL Clipboard is a dockable tool that stores the history of all SQL and PL/SQL code you copy to the Windows clipboard, so that you can paste the clipboard item again in the future....

    plsqldev12.0.6.1832x32主程序+ v12中文包+keygen

    The new PL/SQL Clipboard is a dockable tool that stores the history of all SQL and PL/SQL code you copy to the Windows clipboard, so that you can paste the clipboard item again in the future....

    plsqldev12.0.6.1832x64主程序+ v12中文包+keygen

    The new PL/SQL Clipboard is a dockable tool that stores the history of all SQL and PL/SQL code you copy to the Windows clipboard, so that you can paste the clipboard item again in the future....

    oracle存储过程语法

    Oracle存储过程是数据库管理系统中的一种重要特性,它允许程序员或数据库管理员编写一组SQL语句和PL/SQL块,这些组合起来可以执行特定的任务。在Oracle数据库中,存储过程不仅可以提高性能,还可以增加代码的安全性...

    PLSQL.Developer(X32) v12.0.1.1814主程序+ v11中文包+keygen

    The new PL/SQL Clipboard is a dockable tool that stores the history of all SQL and PL/SQL code you copy to the Windows clipboard, so that you can paste the clipboard item again in the future....

    plsqldev12.0.4.1826x32主程序+ v12中文包+keygen

    The new PL/SQL Clipboard is a dockable tool that stores the history of all SQL and PL/SQL code you copy to the Windows clipboard, so that you can paste the clipboard item again in the future....

    PLSQL.Developer(X64) v12.0.1.1814 主程序+ v11中文包+keygen

    The new PL/SQL Clipboard is a dockable tool that stores the history of all SQL and PL/SQL code you copy to the Windows clipboard, so that you can paste the clipboard item again in the future....

    oracle 存储过程(6)

    -- 定义过程体,包括SQL和PL/SQL语句 EXCEPTION -- 异常处理部分 END procedure_name; ``` 其中,`procedure_name`是存储过程的名称,`parameter_list`为参数列表,`IS`或`AS`关键字后是过程的定义,包括局部变量...

    sql调用webservice

    在Oracle中,可以编写如下PL/SQL代码: ```sql DECLARE l_http_request UTL_HTTP.REQ; l_xml_response CLOB; BEGIN l_http_request := UTL_HTTP.BEGIN_REQUEST('http://example.com/webservice.asmx/Method', '...

    Oracle存储过程基本语法介绍

    Oracle存储过程是数据库管理系统Oracle中的一种重要特性,用于封装一系列SQL和PL/SQL语句,以便重复使用和提高代码效率。下面将详细讲解Oracle存储过程的基本语法和注意事项。 首先,创建一个存储过程的基本语法...

    oracle txt

    - `oracle-5.txt`:可能包含PL/SQL块(BEGIN...END),用于编写存储过程、函数、触发器和游标,这些是数据库操作的重要部分。 - `oracle10-1.txt`、`oracle10-2.txt`:可能涉及Oracle 10g版本特有的特性或优化技巧...

    Packt.PostgreSQL.Developer's.Guide.2015

    - 示例: `UPDATE customers SET email = 'john.doe@example.com' WHERE id = 1;` - **删除数据**: 使用 `DELETE FROM` 删除记录。 - 示例: `DELETE FROM customers WHERE id = 1;` **1.4 PostgreSQL 支持的数据...

    oracle常用问题解答

    **解答**: 在PL/SQL中,可以通过`EXCEPTION`块来自定义异常。定义自定义异常后,可以在程序中使用`RAISE`语句抛出异常。 - **示例**: 定义并抛出自定义异常: ```sql DECLARE e_custom_exception EXCEPTION; ...

    J2EE与数据库.docx

    -- SQL 语句或 PL/SQL 块 EXCEPTION WHEN others THEN -- 异常处理 END; ``` #### 十、Oracle 中 `DISTINCT` **知识点解析:** `DISTINCT` 关键字用于从查询结果中去除重复的行,确保每个结果都是唯一的。 **...

Global site tag (gtag.js) - Google Analytics