PL / SQL - 异常

在本章中,我们将讨论PL/SQL中的异常.例程是程序执行期间的错误条件. PL/SQL支持程序员在程序中使用 EXCEPTION 块来捕获这些条件,并对错误条件采取适当的操作.有两种类型的例外和减号;

  • 系统定义的例外

  • 用户定义的例外

异常处理语法

异常处理的一般语法如下.在这里,您可以列出尽可能多的例外情况.默认例外将使用 处理其他人那么 :

DECLARE 
   <declarations section> 
BEGIN 
   <executable command(s)> 
EXCEPTION 
   <exception handling goes here > 
   WHEN exception1 THEN  
      exception1-handling-statements  
   WHEN exception2  THEN  
      exception2-handling-statements  
   WHEN exception3 THEN  
      exception3-handling-statements 
   ........ 
   WHEN others THEN 
      exception3-handling-statements 
END;

示例

让我们编写一个代码来说明这个概念.我们将使用我们在前面章节中创建和使用的CUSTOMERS表 :

DECLARE 
   c_id customers.id%type := 8; 
   c_name customerS.Name%type; 
   c_addr customers.address%type; 
BEGIN 
   SELECT  name, address INTO  c_name, c_addr 
   FROM customers 
   WHERE id = c_id;  
   DBMS_OUTPUT.PUT_LINE ('Name: '||  c_name); 
   DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr); 

EXCEPTION 
   WHEN no_data_found THEN 
      dbms_output.put_line('No such customer!'); 
   WHEN others THEN 
      dbms_output.put_line('Error!'); 
END; 
/

当在SQL提示符下执行上述代码时,它会产生以下结果 :

No such customer!  

PL/SQL procedure successfully completed.

上述程序显示已提供ID的客户的名称和地址.由于我们的数据库中没有ID值为8的客户,程序会引发运行时异常 NO_DATA_FOUND ,该异常在 EXCEPTION块中捕获.

引发异常

只要有内部数据库错误,数据库服务器就会自动引发异常,但程序员可以使用命令

DECLARE 
   exception_name EXCEPTION; 
BEGIN 
   IF condition THEN 
      RAISE exception_name; 
   END IF; 
EXCEPTION 
   WHEN exception_name THEN 
   statement; 
END;

您可以使用上述语法来引发Oracle标准异常或任何用户定义的异常.在下一节中,我们将举例说明如何引发用户定义的异常.您可以用类似的方式引发Oracle标准异常.

用户定义的异常

PL/SQL允许您根据以下内容定义自己的异常您的计划的需要.必须声明用户定义的异常,然后使用RAISE语句或过程 DBMS_STANDARD.RAISE_APPLICATION_ERROR 显式引发.

声明异常的语法是 :

DECLARE 
   my-exception EXCEPTION;

示例

以下示例说明了这一概念.该程序要求提供客户ID,当用户输入无效ID时,会引发异常 invalid_id .

DECLARE 
   c_id customers.id%type := &cc_id; 
   c_name customerS.Name%type; 
   c_addr customers.address%type;  
   -- user defined exception 
   ex_invalid_id  EXCEPTION; 
BEGIN 
   IF c_id <= 0 THEN 
      RAISE ex_invalid_id; 
   ELSE 
      SELECT  name, address INTO  c_name, c_addr 
      FROM customers 
      WHERE id = c_id;
      DBMS_OUTPUT.PUT_LINE ('Name: '||  c_name);  
      DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr); 
   END IF; 

EXCEPTION 
   WHEN ex_invalid_id THEN 
      dbms_output.put_line('ID must be greater than zero!'); 
   WHEN no_data_found THEN 
      dbms_output.put_line('No such customer!'); 
   WHEN others THEN 
      dbms_output.put_line('Error!');  
END; 
/

当在SQL提示符下执行上述代码时,它会产生以下结果 :

Enter value for cc_id: -6 (let's enter a value -6) 
old  2: c_id customers.id%type := &cc_id; 
new  2: c_id customers.id%type := -6; 
ID must be greater than zero! 
 
PL/SQL procedure successfully completed.

预定义的异常

PL/SQL提供了许多预定义的异常,这些异常在任何数据库规则时执行被程序侵犯.例如,当SELECT INTO语句不返回任何行时,将引发预定义的异常NO_DATA_FOUND.下表列出了一些重要的预定义异常 :

ExceptionOracle ErrorSQLCODE描述
ACCESS_INTO_NULL06530-  6530当空对象自动赋值时引发.
CASE_NOT_FOUND06592-  6592如果没有选择CASE语句的WHEN子句中的任何选项,并且没有ELSE子句,则引发它.
COLLECTION_IS_NULL06531-> 6531当程序尝试将EXISTS以外的集合方法应用于未初始化的嵌套表或varray时,或程序尝试赋值时引发到未初始化的嵌套表或varray的元素.
DUP_VAL_ON_INDEX00001-  1尝试将重复值存储在具有唯一索引的列中时引发它.
INVALID_CURSOR01001-> 1001当尝试进行不允许的游标操作时会引发它,例如关闭未打开的游标.
INVALID_NUMBER01722-> 1722当字符串转换为数字失败时引发它,因为字符串不代表有效数字.
LOGIN_DENIED01017-  1017当程序尝试使用无效的用户名或密码登录数据库时引发.
NO_DATA_FOUND01403+ 100当SELECT INTO语句没有返回任何行时引发它.
NOT_LOGGED_ON01012-  1012在未连接数据库的情况下发出数据库调用时引发.
PROGRAM_ERROR06501-  6501当PL/SQL出现内部问题时会引发它.
ROWTYPE_MISMATCH06504-> 6504当游标在具有不兼容数据类型的变量中获取值时引发它.
SELF_IS_NULL30625-> 30625调用成员方法时引发它,但未初始化对象类型的实例.
STORAGE_ERROR06500-  6500当PL/SQL内存不足或内存损坏时引发它.
TOO_MANY_ROWS01422-> 1422当SELECT INTO语句返回多行时引发它.
VALUE_ERROR06502-> 6502当发生算术,转换,截断或尺寸约束错误时引发它.
ZERO_DIVIDE014761476当尝试将数字除以零时,它会被引发.