1、异常 OracleSQL和PL SQL编程 目标 了解PL SQL块的异常处理部分的用途捕获PL SQL块中预定义的异常捕获PL SQL块中的用户定义异常 异常处理 EXCEPTION是在执行PL SQL块时发生了一个错误的信号 最常见的异常是NO DATA FOUND TOO MANY ROWS ZERO DIVIDE例如 假设创建了一个PL SQL块从books表中检索一行 查找一本零售价超过100美元的图书 在这个例子中 因为books表中任何一本书的零售价格都低于100美元 所以从这个表中检索不到任何图书 因此 在执行循环时 没有任何行需要处理 并且返回NO DATA FOUND消息
2、异常处理 在没有找到要处理的行时 就说Oracle 抛出 或 引发 了一个异常 在引发了一个异常时 可以使用异常处理部分来 捕获 这个异常并处理它 PL SQL块异常处理部分语法 EXCEPTIONWHENexception typeTHENstatements WHENexception typeTHENstatements WHENOTHERSTHENstatements 异常处理 示例 从表中没有检索到任何行时引发的异常 DECLAREv titlebooks title TYPE v retailbooks retail TYPE BEGINSELECTtitle retailINTO
3、v title v retailFROMbooksWHEREretail 100 EXCEPTIONWHENNO DATA FOUNDTHENDBMS OUTPUT PUT LINE Norowsretrievedfromthetable END 用户定义的异常处理处理Oracle错误代码 无论什么时候在PL SQL块中发生了错误 Oracle服务器都会返回一个错误代码 比如下图ORA 01422 指出了SELECT语句返回了太多的行 在Oracle中 这种特定的错误类型已经预定义为TOO MANY ROWS DECLAREv titlebooks title TYPE v retailboo
4、ks retail TYPE BEGINSELECTtitle retailINTOv title v retailFROMbooksNATURALJOINorderitemsWHEREorder 1012 DBMS OUTPUT PUT LINE Bookstitle v title Retailprice v retail END 错误代码 用户定义的异常处理处理Oracle错误代码 捕获预定义的异常类型非常简单 用户只需要在块的异常处理部分指定这种类型即可 如果发生了相关联的错误代码 那么就将捕获这个异常 有时候可能会发生某种没有预定义的异常 在这种情况下 用户必须明确引发这个异常 然后
5、可以通过异常处理部分来捕获它 用户定义的异常处理处理Oracle错误代码 当希望捕获一个没有预定义的出错消息 Oracle错误代码 时 需要执行下面的三个步骤 1 必须在PL SQL块的声明部分声明异常的名称 为异常指定的数据类型是EXCEPTION 2 必须使用PRAGMAEXCEPTION INIT语句将所声明的异常与Oracle服务器错误代码相关联 3 必须在PL SQL块的异常处理部分包含所声明的异常 用户定义的异常处理处理Oracle错误代码 示例 捕获用户自定义的异常假设你正在创建一个向PUBLISHER表中添加新出版社的PL SQL块 可能出现的一个问题是将一个现有的出版社ID指
6、定给了一个新项目 因为PUBLISHER表已经存在PRIMARYKEY约束 所以两个出版社不能具有相同的ID 因此将发生一个错误 具体说 Oracle将返回一个ORA 00001错误 如果发生了这种错误 那么可以创建一个消息来警告用户这个ID以及指定给了其他出版社 用户定义的异常处理处理Oracle错误代码 分析 第一步是选择异常的名称 因为在一个PL SQL块中包含多个异常处理语句 所以这个名称应该说明异常的用途 该例中可以使用名称ID ALREADY IN USE 声明这个异常正确的语法 id already in useEXCEPTION 在声明了这个异常之后 必须使用PRAGMAEXC
7、EPTION INIT语句将它与特定的Oracle错误号相关联 PL SQL只能引用已经声明的变量 PRAGMAEXCEPTION INIT语句的语法 示例中 将错误号与该异常关联如下 PRAGMAEXCEPTION INIT id already in use 00001 PRAGMAEXCEPTION INIT exception name errornumber 用户定义的异常处理处理Oracle错误代码 完整示例 DECLAREid already in useEXCEPTION PRAGMAEXCEPTION INIT id already in use 00001 BEGININS
8、ERTINTOpublisherVALUES 1 ANEWPUBLISHER GUYSMART 800 555 2211 EXCEPTIONWHENid already in useTHENDBMS OUTPUT PUT LINE PleasechooseanotherpublisherID END 用户自定义的异常处理RAISE语句触发异常 当与一个异常错误相关的错误出现时 就会隐含触发该异常错误 用户定义的异常错误可以通过显式使用RAISE语句来触发 当引发一个异常错误时 控制就转向到EXCEPTION块异常错误部分 执行错误处理代码 用户自定义的异常处理RAISE语句触发异常 对于这类异
9、常情况的处理 步骤如下 1 在PL SQL块的定义部分定义异常情况 EXCEPTION 2 RAISE 3 在PL SQL块的异常情况处理部分对异常情况做出相应的处理 用户自定义的异常处理RAISE语句触发异常 示例 删除指定编号图书 DECLAREv isbnbooks isbn Type 总结 如果在PL SQL块的可执行部分发生了一个非语法错误 那么将引发一个异常 PL SQL块的异常处理部分用来在捕获这个块中引发的错误 如果没有捕获一个错误 那么这个块的执行将异常中断 这个错误将传播到外部的任何块或者调用环境如果捕获了一个错误 那么这个块将成功执行 异常将不会传播到外部的任何块或调用环境必须声明非预定的异常才能将其与一个Oracle服务器错误号相关联 2020 6 15 Inspurgroup 谢谢大家