和其它开发语言一样,PL/SQL在运行过程中会出现各种错误,也就是异常,这些异常有的来自程序本身,有的来自开发人员。PL/SQL采用了统一捕获并处理异常的方式,异常发生,程序跳转到 异常块 进行匹配,然后进行处理,如果不捕获异常的话,PL/SQL程序会停止运行。
一、异常块语法
1、语法
EXCEPTION
WHEN exception1 [or exception2...] THEN --异常匹配1
statement; --处理
WHEN exception3 THEN --异常匹配2
statement; --处理
......
WHEN OTHERS THEN --都不匹配时处理(可选)
statement;
可以有多个WHEN ... THEN来进行异常匹配,一个异常匹配里面也可以用or来匹配多个异常.
2、示例
declare
v_result number(10);
begin
v_result := 1/0;
DBMS_OUTPUT.PUT_LINE('结果是' || v_result);
exception
when ZERO_DIVIDE then
DBMS_OUTPUT.PUT_LINE('除数不能为0');
end;
二、异常分类
PL/SQL中异常可以分为3类:
1)预定义异常
2)非预定义异常
3)自定义异常
前2个都是Oracle中的错误,程序中出现时会自动触发,而自定义异常是开发人员定义的异常,不会自动触发,需要手动触发.
1、预定义异常
Oracle中为每个错误提供了一个错误号,而捕获异常需要有名称。Oracle提供了一些已经 定义了名称 的异常,这就是预定义异常,下面列出开发中常用的预定义异常:
Exception(异常名) | ORA Error | 触发异常的条件 |
---|---|---|
NO_DATA_FOUND | ORA-01403 | select...into语句没有返回记录 |
TOO_MANY_ROWS | ORA-01422 | select...into语句返回记录多于一条 |
CASE_NOT_FOUND | ORA-06592 | case语句都不匹配,并且没有else语句 |
DUP_VAL_ON_INDEX | ORA-00001 | 索引对应的列上出现重复值 |
VALUE_ERROR | ORA-06502 | 赋值时,变量长度不够 |
ZERO_DIVIDE | ORA-01476 | 除数为零时 |
CURSOR_ALREADY_OPEN | ORA-06501 | 游标重复打开 |
INVALID_CURSOR | ORA-01001 | 游标使用不合法,例::未打开游标就提取数据、关闭未打开的游标 |
当然,上面只是用的比较多的一些预定义异常,通过下面的查询语句可以查看Oracle中所有的预定义异常:
select * from dba_source where
name = 'STANDARD' and text like '%EXCEPTION_INIT%';
2、非预定义异常
Oracle中更多的还是非预定义异常,也就是只有错误编号和错误描述的异常,而没有名称的异常不能被捕获,所以需要为非定义异常定义名称.
非预定义异常的使用分为3步:
1)、声明异常的名称
2)、将名称和异常编号关联
3)、在异常块处捕捉异常
示例:
DECLARE
my_excep EXCEPTION; --声明异常的名称
PRAGMA EXCEPTION_INIT(my_excep,-2291); --将名称和异常编号关联
BEGIN
UPDATE product SET cid = '666' where pid = '1';
EXCEPTION --在异常块处捕捉异常
WHEN my_excep THEN
DBMS_OUTPUT.PUT_LINE('该商品分类不存在');
END;
商品表product和分类表category存在主外键关系,在category表中不存在分类cid为'666'的分类,所以执行上面的SQL时会触发ORA-02291对应的异常.
3、自定义异常
开发中有些业务可能有特别的需求,比如性别只能是男、女,年龄不能为负数等等,这些和业务相关的不算系统的错误,如果我们要用异常的方式来处理,必须自定义异常,并显示触发.
自定义异常的使用分为4步:
1)声明异常的名称
2)为异常关联一个错误编号,值可以是-20999~-20000之间的负整数
3)利用RAISE关键字手动抛出异常
4)在异常块处捕捉异常
示例:
DECLARE
my_excep EXCEPTION; --声明异常的名称
PRAGMA EXCEPTION_INIT(my_excep,-20333); --为异常关联一个错误编号
v_num number(10);
BEGIN
select p.num into v_num from product p where p.pid = '1';
IF v_num < 0 THEN
RAISE my_excep; --手动抛出异常
END IF;
EXCEPTION --在异常块处捕捉异常
WHEN my_excep THEN
DBMS_OUTPUT.PUT_LINE('商品数量不能为负数');
END;
三、使用异常函数
在PL/SQL中可以通过异常函数来获取异常的相关信息.
1)SQLCODE获取异常编号
2)SQLERRM获取异常信息
declare
v_result number(10);
begin
v_result := 1/0;
DBMS_OUTPUT.PUT_LINE('结果是' || v_result);
exception
when ZERO_DIVIDE then
DBMS_OUTPUT.PUT_LINE('异常编号为:' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('异常信息为:' || SQLERRM);
end;
![](https://img.haomeiwen.com/i5586232/8bd7d1a611a8325d.png)
网友评论