一个优秀的程序都应该能够正确的处理各种出错异常,并尽可能的从错误中恢复,ORACLE提供异常来实现错误处理,
异常exception这个词还是这个,处理正常执行过程中未预料的事件,他分为预定义的错误,和自定义的错误,相当于
还可以自定义一个异常,由于PL/SQL块一旦产生异常,没有指出如何处理,程序就会自动的终止程序的运行,自动终止
程序的运行,就像JAVA里面也是一样的,他这里有三种异常的错误,第一种叫预定义的,预定义的大概有24种异常,然后这个时候
它会自动的给你抛出来如果你不使用exception给他捕获的话,那他就在这里停止了,如果你要捕获,你就使用exception给他
处理一下,这跟JAVA是一样的,非预定义的异常,就是其他标准的ORACLE错误,也是ORACLE指定的一个错误,但是他这个错误
和你自己定义的错误,来练习起来,然后自定义一个名,我们来说这两个怎么来写,比如我想查询一个人的工资,如果查工资低于
2千,工资太低本来没有啥问题,你只要这个工资低于多少钱,我就让你抛一个异常,就是你可以自定义一个异常,然后异常的格式,
在大的PL/SQL块里边,叫exception,在这里边写,如何处理这个异常,当时这个类型的时候,then如何处理,当你有多个异常,
when then,when other then
处理异常的方式,预定义的异常大概有24种,异常的情况,有错误号,其他错误的信息,要想捕获这个
异常,错误号它是自动会爆出来的,你把这个内容放到这,比如no_data_found,没有找到数据,你想更新里面的
一个人的工资,结果没有找到一条数据,他就会抛1403的错误,when no_data_found,then 打印一条说,没有找到数据
他里面有这个类型的,叫to_many_rows,我就查询一下,declare,定义一个叫v_salary,employees表里面,
salary,百分号,type,begin,select salary into v_salary,然后from employees,where,我先写一个100,
就是把100号的工资放到v_salary,dbms打印v_salary,这个程序,我们写上这个,exception,我们知道这里面可能
会出现什么异常,when..then..,这个发现没问题,100号的工资是24240
declare
v_salary employees.salary%type;
begin
select salary into v_salary from employees
where employee_id = 100;
dbms_output.put_line(v_salary);
end;
这儿这个程序,我们写上也行,只是我们现在不知道这里面会出现什么异常,我们这里改成一个大于,这显然不是一个人的
员工的查询结果了,正常我们要使用游标,这是多条记录,现在这里实际上是多条记录,实际返回的行数超出请求的行数
declare
v_salary employees.salary%type;
begin
select salary into v_salary
from employees
where employee_id > 100;
end;
too_many_rows这就是他错误的名字,错误的标号,那我在我相应的exception这里,when,叫to_many_rows,then,
输出的行数太多了,就这样写,这不就执行了
declare
v_salary employees.salary%type;
begin
select salary into v_salary
from employees
where employee_id > 100;
dbms_output.put_line(v_salary);
exception
when too_many_rows then dbms_output.put_line('输出的行数太多了!!!!!');
end;
输出的行数太多了,就这样写,相当于他抛出来这样一个对象一样,然后我们看这个对象对应的类型,
是这个类型的你给他输出,你也可以给他补一下,when others then,出现其他类型的异常的时候,这个就叫
预定义的异常,就是他出现异常的错误在这里面有标识了
declare
v_salary employees.salary%type;
begin
select salary into v_salary
from employees
where employee_id > 100;
dbms_output.put_line(v_salary);
exception
when too_many_rows then dbms_output.put_line('输出的行太多了!!');
when others then dbms_output.put_line('出现其他类型的异常了!');
end;
非预定义异常的处理,我们需要再PL/SQL块中声明一个异常,然后把你出现的错误代码,跟我这个异常的对象,
关联起来,使用这样一个语句,给我们操作一个
我使用SQL语句写一个,delete from employees,where employee_id等于100,说违反完整性约束条件
这个删除知道为什么不能删吗,外键有一个manager_id,但是manager_id是指向你自己的employee_id,
你删除这个主键的时候,外键manager_id有人指向他,所以他不让你删,这个叫2292,报这个错,这里面没有
2292,要是有的话你就when处理,他没有这个错误的24种,那你就得这样写,declare,那你就得自己定义这个
异常,叫delete_id,e_deleteid_exception,exception类型的,光这样写还不行,你得使用这个语句,给他关联起来,
pragma,是这样,然后把你这个名放到这,刚才出现这个错误号,2292,-2292,这就写完了,然后呢,begin,我们刚才想
删除的放到这,delete from,where,100号员工删除,他一删除的时候,他就抛这个错,然后exception,when,当你出现
这个异常的时候,违反完整性约束条件,故不可以删除此用户,end
declare
v_deleteid_exception exception;
pragma exception_init(e_deleteid_exception,-2292);
begin
delete from employees where employee_id = 100;
exception
when e_deleteid_exception then dbms_output.put_line('违反完整性约束条件,故不可以删除此用户!');
end;
他就不给你报这个错了,第一种区别呢,我们试图去查询一下salary的工资,结果我们发现长度过多了,
就因为这个错误,发现这个框里有,有的话,我们就可以用预定义的异常,结果这里有一些错误,发现他
报的号我这个表里找不到,既然这个号又给你爆出来了,说明ORACLE已经定义了这个错误,他有这个错,
那为就把这个错和我定义的异常关联起来,我就可以定义exception的类型一样,然后让这个变量和错误的
关联起来,当你一旦执行这个语句,发现发生这个错误编号的时候,就自动让你转成这个异常的变量,然后再给他
输出出来,这就叫非预定义异常,有预定义的异常,有非预定义的异常,还有个叫用户自定义的异常,用户自定义的,
用户定义的异常错误是显示用RAISE语句来触发的,当引发异常错误的时候,控制就会转向到EXCEPTION块异常错误的部分,
执行错误的代码,看看这个
我们这样,还是查询100号员工的工资,如果他的工资大于1万,我就抛一个异常说,工资太高了,
declare,还得声明一个异常的变量,e_too_high_sal,exception类型的,他得定义一个变量,整体要查的
员工的工资,然后begin,select salary into v_sal,from employees这个表,where employee_id等于100,
把100号员工的工资查出来,如果v_sal查出来大于1万的,then就处理,那怎么处理,就抛这个异常,如果你要是小于
1万的,我就不给你处理了,我就直接end if结束,没了,end,忘了exception了,你抛出来了你还没有处理呢,when,当你
发生这个异常的时候,then,dbms_output.put_line,打印,相当于你这个异常到底是干什么的,工资太高了,就这样一个,
declare
e_too_high_sal_exception;
v_sal employees.salary%type;
begin
select salary into v_sal from employees where employee_id = 100;
if v_sal > 10000 then
raise e_too_high_sal;
end if;
exception
when e_too_high_sal then dbms_output.put_line('工资太高了!');
end;
相当于你这个异常是干什么的,工资太高了,这样一个,这个就叫用户自定义的异常,我们刚才定义的三个其实是
分开写的,你也可以给合起来,这个没问题,就是整个放在一起的话,我们有一个删除的,删除的在这,就是刚才这个,
delete的错误,delete里面我定义了这两个,非预定义的异常,然后执行一个delete,你们就看谁先执行,谁后执行了,
放在这的话detele先执行,delete如果没错的话,那就删了,有错的话,他就直接跑到这儿来了,你也可以再加上一个when,
others then,发生其他的异常了,然后给他end,执行的话只要你执行出现异常了,我就exception我就去找,后边的代码
就不再执行了,后边就会抛这个异常
这里就相当于子程序来执行,只要你执行到哪一块出现异常了,我就去exception里面去找,后边的代码就不再执行了,
所以就会抛这个异常,因为你这一块代码不会被执行,就这个意思,这是说的异常,异常后边还有一些练习,这三种异常的形式,
18. 异常的基本程序:
通过 select ... into ... 查询某人的工资, 若没有查询到, 则输出 "未找到数据"
declare
--定义一个变量
v_sal employees.salary%type;
begin
--使用 select ... into ... 为 v_sal 赋值
select salary into v_sal from employees where employee_id = 1000;
dbms_output.put_line('salary: ' || v_sal);
exception
when No_data_found then
dbms_output.put_line('未找到数据');
end;
或
declare
--定义一个变量
v_sal employees.salary%type;
begin
--使用 select ... into ... 为 v_sal 赋值
select salary into v_sal from employees;
dbms_output.put_line('salary: ' || v_sal);
exception
when No_data_found then
dbms_output.put_line('未找到数据!');
when Too_many_rows then
dbms_output.put_line('数据过多!');
end;
如若没找到,就输出未找到数据,未找到数据,你先这样看一下,我们写这个题,你说这个叫预定义,
或者非预定义,这个也不好说,那你就先让他执行一下,他说让你查询某个人的工资,看这个人有没有,
我就declare,begin,select salary into,from employees,where,这样处理的话肯定没有问题,end他就能够找到,
他找到给他打印一下
declare
v_sal employees.salary%type;
begin
select salary into v_sal from employees where employee_id = 100;
dbms_output.put_line(v_sal);
end;
这是他的工资,然后你要输出比如1001,这人不在,说未找到数据,这不就出现一个异常吗,ORA-1403,你在这找找
declare
v_sal employees.salary%type;
begin
select salary from employees where employee_id = 1001;
dbms_output.put_line(v_sal);
end;
有的话就是预定义的,没有的话你得自己去定义一个,1403就是这个吧,有这个就好办了,就是预定义的,
就是定义好的
在这儿,exception,when,no_data_found,then,查无此人,那就这样子,这个就相当于叫预定义的
declare
v_sal employees.salary%type;
begin
select salary into v_sal from employees where employee_id = 100;
dbms_output.put_line(v_sal);
exception
when no_data_found then dbms_output.put_line('查无此人');
end;
这个相当于是预定义的,还有对应的异常的类型,没有的话就自己造一个
19. 更新指定员工工资,如工资小于300,则加100;对 NO_DATA_FOUND 异常, TOO_MANY_ROWS 进行处理.
declare
v_sal employees.salary%type;
begin
select salary into v_sal from employees where employee_id = 100;
if(v_sal < 300) then update employees set salary = salary + 100 where employee_id = 100;
else dbms_output.put_line('工资大于300');
end if;
exception
when no_data_found then dbms_output.put_line('未找到数据');
when too_many_rows then dbms_output.put_line('输出的数据行太多');
end;
如果工资小于300,加100,对于没有找到数据的,还有输出行太多的,更新指定员工的工资,如果工资小于300,
指定员工的,工资小于300,也得先定义一个工资,然后把工资给他放在这里边,假设101这个人,放到这里面,然后,
我判断一下,这个v_sal他是否是小于300的,如果是小于300的,则加100,then的话加100,salary加100,then相当于
做一个更新操作,如果你这个人的工资小于300,我就update,employees,set,salary等于salary加上100,指定员工的,
这是对于确实小于100,如果你这个员工可能不在,不在的话就输出他,还有可能说你写的这个salary,employee_id,
when too_many_rows,then,输出的行太多了,就这样处理,101我们看这个,end if,说明就没有异常
declare
v_sal employees.salary%type;
begin
select salary into v_sal from employees where employee_id = 101;
if v_sal<300 then update employees set salary=salary+100 where employee_id = 101;
end if;
exception
when no_data_found then dbms_output.put_line('查无此人');
when too_many_rows then dbms_output.put_line('输出的行数太多了!');
end;
20. 处理非预定义的异常处理: "违反完整约束条件"
declare
--1. 定义异常
temp_exception exception;
--2. 将其定义好的异常情况,与标准的 ORACLE 错误联系起来,使用 EXCEPTION_INIT 语句
PRAGMA EXCEPTION_INIT(temp_exception, -2292);
begin
delete from employees where employee_id = 100;
exception
--3. 处理异常
when temp_exception then
dbms_output.put_line('违反完整性约束!');
end;
删除这个人,包2292这个异常,关联起来,然后在when这里接收
21. 自定义异常: 更新指定员工工资,增加100;若该员工不存在则抛出用户自定义异常: no_result
declare
--自定义异常
no_result exception;
begin
update employees set salary = salary + 100 where employee_id = 1001;
--使用隐式游标, 抛出自定义异常
if sql%notfound then
raise no_result;
end if;
exception
--处理程序抛出的异常
when no_result then
dbms_output.put_line('更新失败');
end;
它使用用户自定义的,正常这个员工不存在的话,直接使用no_data_found就可以了,还有想用户自定义的也行,
update employees set salary = salary + 100,当employee_id是他的时候,它使用的叫隐式游标,因为这个是异常数据,
判断是否在,就raise一个异常,这个对象是我自定义的,我们看一下就行,更新失败
declare
no_result exception;
begin
update employees set salary = salary + 100 where employee_id = 100;
if sql%notfound then
raise no_result;
end if;
exception
when no_result then
dbms_output.put_line('更新失败');
end;