在本章中,无涯教程将讨论PL/SQL中的异常,异常是程序执行期间的错误条件, PL/SQL支持程序员使用程序中的 EXCEPTION 块捕获此类条件,并针对错误条件采取适当的措施。有两种类型的异常-
异常处理的一般语法如下,在这里,您可以列出尽可能多的异常,默认异常将使用 当其他则THEN 处理-
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块中捕获。
每当有内部数据库错误时,数据库服务器都会自动引发异常,但是程序员可以使用命令 RAISE 明确地引发异常。以下是引发异常的简单语法-
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。
异常 | Oracle错误 | SQLCODE | 说明 |
---|---|---|---|
ACCESS_INTO_NULL | 06530 | -6530 | 为空对象自动分配值时引发。 |
CASE_NOT_FOUND | 06592 | -6592 | 当没有选择CASE语句的WHEN子句中的任何选择,并且没有ELSE子句时,将引发它。 |
COLLECTION_IS_NULL | 06531 | -6531 | 当程序尝试将EXISTS之外的其他收集方法应用于未初始化的嵌套表或varray,或者程序尝试将值分配给未初始化的嵌套表或varray的元素时,会引发该错误。 |
DUP_VAL_ON_INDEX | 00001 | -1 | 当尝试将重复值存储在具有唯一索引的列中时引发。 |
INVALID_CURSOR | 01001 | -1001 | 在尝试进行不允许的光标操作(如关闭未打开的光标)时会引发该错误。 |
INVALID_NUMBER | 01722 | -1722 | 由于字符串不能代表有效数字而导致字符串转换为数字失败时引发。 |
LOGIN_DENIED | 01017 | -1017 | 当程序尝试使用无效的用户名或密码登录数据库时引发。 |
NO_DATA_FOUND | 01403 | + 100 | 当SELECT INTO语句不返回任何行时引发。 |
NOT_LOGGED_ON | 01012 | -1012 | 在未连接数据库的情况下发出数据库调用时引发。 |
PROGRAM_ERROR | 06501 | -6501 | 当PL/SQL存在内部问题时引发。 |
ROWTYPE_MISMATCH | 06504 | -6504 | 当游标获取数据类型不兼容的变量中的值时引发。 |
SELF_IS_NULL | 30625 | -30625 | 在调用元素方法但未初始化对象类型的时引发。 |
STORAGE_ERROR | 06500 | -6500 | 当PL/SQL内存不足或内存损坏时会引发该错误。 |
TOO_MANY_ROWS | 01422 | -1422 | 当SELECT INTO语句返回多行时引发。 |
VALUE_ERROR | 06502 | -6502 | 在发生算术,转换,截断或大小约束错误时引发。 |
ZERO_DEVIDE | 01476 | 1476 | 尝试将数字除以零时引发。 |
祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)