抛出异常
Oracle有三种类型的异常错误:
1. 预定义(Predefined)异常
ORACLE预定义的异常情况大约有24个。对这种异常情况的处理,无需在程序中定义,由ORACLE自动将其引发。
2. 非预定义(Predefined)异常
即其他标准的ORACLE错误。对这种异常情况的处理,需要用户在程序中定义,然后由ORACLE自动将其引发。
3. 用户定义(User_define)异常
程序执行过程中,出现编程人员认为的非正常情况。对这种异常情况的处理,需要用户在程序中定义,然后显式地在程序中将其引发。
在PL/SQL中有三种方式抛出异常
通过PL/SQL运行时引擎——抛出Oracle异常
使用RAISE语句——抛出用户定义异常
调用RAISE_APPLICATION_ERROR存储过程——抛出用户定义异常
1、预定义异常是指oracle系统为一些常见错误定义好的异常,例如表中的主键值重复,以及除数为0等。
oracle预定义异常:
命名的系统异常 | 产生原因 |
ACCESS_INTO_NULL | 未定义对象 |
CASE_NOT_FOUND | CASE 中若未包含相应的 WHEN ,并且没有设置 ELSE 时 |
COLLECTION_IS_NULL | 集合元素未初始化 |
CURSER_ALREADY_OPEN | 游标已经打开 |
DUP_VAL_ON_INDEX | 唯一索引对应的列上有重复的值 |
INVALID_CURSOR | 在不合法的游标上进行操作 |
INVALID_NUMBER | 内嵌的 SQL 语句不能将字符转换为数字 |
NO_DATA_FOUND | 使用 select into 未返回行,或应用索引表未初始化的元素时 |
TOO_MANY_ROWS | 执行 select into 时,结果集超过一行 |
ZERO_DIVIDE | 除数为 0 |
SUBSCRIPT_BEYOND_COUNT | 元素下标超过嵌套表或 VARRAY 的最大值 |
SUBSCRIPT_OUTSIDE_LIMIT | 使用嵌套表或 VARRAY 时,将下标指定为负数 |
VALUE_ERROR | 赋值时,变量长度不足以容纳实际数据 |
LOGIN_DENIED | PL/SQL 应用程序连接到 oracle 数据库时,提供了不正确的用户名或密码 |
NOT_LOGGED_ON | PL/SQL 应用程序在没有连接 oralce 数据库的情况下访问数据 |
PROGRAM_ERROR | PL/SQL 内部问题,可能需要重装数据字典& pl./SQL 系统包 |
ROWTYPE_MISMATCH | 宿主游标变量与 PL/SQL 游标变量的返回类型不兼容 |
SELF_IS_NULL | 使用对象类型时,在 null 对象上调用对象方法 |
STORAGE_ERROR | 运行 PL/SQL 时,超出内存空间 |
SYS_INVALID_ID | 无效的 ROWID 字符串 |
TIMEOUT_ON_RESOURCE | Oracle 在等待资源时超时 |
TOO_MANY_ROWS | SELECT INTO 语句返回多条记录 |
VALUE_ERROR | 发生算术,转换,截断或大小约束错误 |
ZERO_DIVIED | 视图讲0作为除数 |
declare
age varchar2(4) := '14岁';
begin
dbms_output.put_line('测试异常发生前的内容有没有执行');
dbms_output.put_line(cast(age as number));
dbms_output.put_line('测试异常发生后的内容有没有执行');
end;
执行的结果:
注意:从执行的结果可以看出,oracle抛出ora-06502异常,提示字符到数值的转换错误,在抛出异常后,由于程序中中没有处理该异常的代码,因此程序终止,所以最后的结果是异常发生前的内容被执行,而之后的内容没有被执行。
对上面的代码进行异常处理:
declare
age varchar2(4) := '14岁';
begin
dbms_output.put_line('测试异常发生前的内容有没有执行');
dbms_output.put_line(cast(age as number));
exception
when VALUE_ERROR then
dbms_output.put_line('异常提示:该字符串不能转换为有效的数字');
dbms_output.put_line('测试异常发生后的内容有没有执行');
end;
执行的结果:
测试异常发生前的内容有没有执行
异常提示:该字符串不能转换为有效的数字
测试异常发生后的内容有没有执行
2、非预定义异常
除了oracle预定义好的异常以外,还有一些其他异常也属于程序本身的逻辑错误,
例如违反表的外键约束、检查约束等,oralce只为这些异常提供了错误代码,而这些异常同样需要处理,只不过学哟啊在pl/sql块中使用pragma execption_init语句为该异常设置名称
declare
sex_check exception;
pragma exception_init(sex_check,-2290);
begin
insert into student values('路');
exception
when sex_check then
dbms_output.put_line('插入的值违反了sex列的检查约束');
end;
/
3、自定义异常
前面提到的异常主要是程序本身的逻辑错误,而在实际应用中,程序员还可以根据需求,为实现具体的业务逻辑自定义相关异常,因为这些业务逻辑是oracle系统无法判断的,例如:不允许删除管理员表中的最该管理员等。
--例9.21假设manager表中有3列。mid(主键列),mname(管理员名称)和mgrade(管理员级别),要求在根据mid值
--删除manager表中的几率是,不能删除mgrade值为1的记录,
--否则返回异常信息这就需要为也为逻辑穿件自定义异常
declare
manager_id number :=1;
manager_grade number;
begin
select mgrade into manager_grade from manager
where mid=manager_id;
if(manager_grade is not null)and (manager_grade=1)
then raise_application_error(-20100,'不能删除管理级别为1的管理员');
end if;
delete from manager where mid=manager_id;
end;