异常
简介
在编写程序的过程中,总会遇到不少的错误
异常包含软件,硬件,网络,程序等运行过程中出现的错误
分类
这些错误有的是由于错误的输入造成的,有的是程序在运行过程中出现的逻辑性存错
oracle中的错误可以分为如下两大类
-
编译时错误:
- 程序在编写过程中出现的错误,pl/sql引擎在进行编译时会发现这些错误
- 并报告给用户,此时程序还没有完全运行
-
运行时错误:
- 程序在运行过程中因为各种各样的原因产生的运行时错误,
- 由于这些错误有时难以预料,因此需要异常处理机制来进行处理
一般在使用时分为两种情况
- 记录错误日志
- 将错误前和错误后,修改前和修改后的记录保存到日志中
内置异常
异常名 | 异常编号 | 异常描述 |
---|---|---|
ACCESS_INTO_NULL: | 对应ORA-06530 | 为了引用对象属性,必须首先初始化对象。直接引用未初始化的对象属性时,会发生异常 |
CASE_NOT_FOUND: | 对应ORA-06592, | 当CASE语句的WHEN子句没有包含必须条件分支或者ELSE子句时,会触发 |
COLLECTION_IS_NULL: | 对应ORA-06531, | 在给嵌套表变量或者varrary变量赋值之前,必须首先初始化集合 |
CURSOR_ALREADY_OPEN: | ORA-06511, | 当已打开游标上执行OPEN操作时会触发 |
INVALID_CURSOR: | ORA-01001, | 当试图从未打开游标,提取数据,或者关闭未打开游标时会触发 |
INVALID_NUMBER: | ORA-01722, | 当内嵌SQL语句不能将字符转变成数字时会触发 |
LOGIN_DENIED: | ORA-01017, | 连接Oracle数据库时,如果提供了不正解的用户名和口令时会触发 |
NO_DATA_FOUND: | ORA-01403 | 执行SELECT INTO 未返回行或者引用了未初始化的PL/SQL表元素时会触发 |
NOT_LOGGED_ON: | ORA-01012 | 没有连接数据库执行SQL时会触发 |
PROGRAM_ERROR: | ORA-06501 | 存在PL/SQL内部问题,在这种情况下需要重新安装数据字典视图和PL/SQL包 |
ROWTYPE_MISMATCH: | ORA-016504 | 当执行赋值操作时,如果宿主变量和游标变量不兼容的返回类型时,会触发 |
SELF_IS_NULL: | ORA-30625, | 当使用对象类型时,如果在null实例上调用成员方法时,会触发 |
STORAGE_ERROR: | ORA-06500 | 当执行PL/SQL块时,如果超出内存空间或者内存被破坏,会触发 |
SUBSCRIPT_BEYOND_COUNT: | ORA-06533 | 当使用嵌套或者varray元素的范围进会触发 |
SUBSCRIPT_OUTSIDE_LIMIT: | ORA-06532, | 使用嵌套表或者varray元素时,如果元素下标为负值时,会触发 |
SYS_INVALID_ROWID: | ORA-01410 | 当字符串转变为ROWID时如果使用了无效字符串,会触发 |
TIMEOUT_ON_RESOURCE: | ORA-00051 | 当等待资源时如果出现超时会触发 |
TOO_MANY_ROWS: | ORA-01422 | 当执行SELECT INTO时,如果返回超过一行、会触发 |
VALUE_ERROR: | ORA-06502, | 执行赋值时,如果变量长度不足,会触发 |
ZERO_DIVIDE: | ORA-01476 | 如果用数字值除0,会触发 |
异常的使用方式
带异常处理的代码块
declare
声明部分
begin
代码块
exception
异常处理部分
end;
异常处理代码块
exception
when 异常名称 then
异常处理代码;
when 异常名称 then
异常处理代码;
...
when others then
异常处理代码;
异常的使用方式:抛出异常,捕获异常
others可以捕获到任何异常
捕获异常
exception中的语法叫做捕获异常
declare
--声明一个emp表的rowtype类型变量
v emp%rowtype;
begin
select * into v from emp where deptno=1;
dbms_output.put_line('hexo');
exception
when no_data_found then
dbms_output.put_line('未找到数据');
end;
输出结果
未找到数据
当程序出现异常时,会跳到exception代码块.错误代码和exception之间的代码不会执行
oracle内置的异常变量
-
sqlcode
: 异常编码- 100表示no_data_found
- 1表示用户自定义异常
- -1表示系统内置异常
-
sqlerrm
: 异常信息
declare
--声明一个emp表的rowrtpe类型变量
v emp%rowtype;
begin
begin
select * into v from emp where empno=1;
exception
when others then
dbms_output.put_line(sqlcode);
dbms_output.put_line(sqlerrm);
end;
dbms_output.put_line('next');
end;
输出
100
ORA-01403: 未找到任何数据
next
抛出异常/自定义异常
定义异常异常名称 exception;
抛出异常raise 异常名称;
declare
--定义一个异常
myexc exception;
begin
--抛出自定义异常
raise myexc;
--捕获异常
exception
when myexc then
dbms_output.put_line(sqlcode);
dbms_output.put_line(sqlerrm);
end;
输出
1
User-Defined Exception
另一个抛出异常的方式
dbms_standard.raise_application_error(异常编码,'异常信息')
抛出一个应用异常(业务异常)
异常编码范围: -20000 ~ -20999
begin
dbms_standard.raise_application_error(-20001,'俺的异常');
exception
when others then
dbms_output.put_line(sqlcode);
dbms_output.put_line(sqlerrm);
end;
输出
-20001
ORA-20001: 俺的异常
异常绑定
通过自定义异常绑定没有名字的异常
语法
pragma exception_init(自定义异常名,异常编码);--声明部分写
declare
--自定义一个异常
myexc exception;
--将-00001的异常绑定到自定义异常上
pragma exception_init(myexc,-00001);
begin
insert into dept values(10,'a','b');
exception
when myexc then
dbms_output.put_line(sqlcode);
dbms_output.put_line(sqlerrm);
end;
输出
-1
ORA-00001: 违反唯一约束条件 (SCOTT.PK_DEPT)
declare
--自定义一个异常
myexcs exception;
--异常绑定
pragma exception_init(myexcs,-20001);
begin
dbms_standard.raise_application_error(-20001,'我的异常');
exception
when myexcs then
dbms_output.put_line(sqlcode);
dbms_output.put_line(sqlerrm);
end;
输出异常
-20001
ORA-20001: 我的异常
文件读写
读写文件方法
读写文件需要用到的包utl_file
utl_file.file_type
作用:文件类型
utl_file.fopen('目录名称','文件名',读写方式)
作用:打开文件
目录名称:是oracle中directory对象名.使用时,目录名要大写
create directory 目录名称 as '系统的文件路径';
如果创建目录提示权限不足,可以:
SQL> grant create any directory to scott;
授权成功。
读写方式
- r 表示只读
- w 表示写
- a 表示追加
url_file.put_line(文件变量,写入的内容);
作用:向文件写入一行数据
utl_file.put_line(文件变量,字符串变量);
作用:将文件中的一行数据读取出来.保存到变量中.
utl_file.fclose(文件变量);
作用:关闭文件
写文件
创建一个目录
create directory filepath as 'D:\1122\test';
declare
--声明文件变量
f utl_file.file_type;
begin
--打开文件,如果文件不存在,则创建,如果文件存在,则覆盖
f:=utl_file.fopen('FILEPATH','1.txt','w');
--向文件中写一行内容
utl_file.put_line(f,'Hello World');
--关闭文件
utl_file.fclose(f);
end;
1.txt
Hello World
把emp表中所有员工编号写入文件
declare
--声明一个文件变量
f utl_file.file_type;
begin
--打开文件
f:=utl_file.fopen('FILEPATH','2.txt','w');
for v in (select empno from emp) loop
--将员工编号写入到文件中
utl_file.put_line(f,v.empno);
end loop;
--关闭文件
utl_file.fclose(f);
end;
2.txt
9123
7777
7369
7499
7521
7566
7654
7698
7782
7788
7839
7844
7876
7900
7902
7934
读文件
declare
--定义一个文件变量
f utl_file.file_type;
--声明一个字符串变量保存文件的一行记录
str varchar2(200);
begin
--打开文件
f:=utl_file.fopen('FILEPATH','2.txt','r');
--循环读取文件
loop
--读取文件的一行记录
utl_file.get_line(f,str);
--打印str变量
dbms_output.put_line(str);
end loop;
--关闭文件
utl_file.fclose(f);
end;
发现可以将文件内容正常输出到屏幕
但是还是报异常
ORA-01403: 未找到任何数据
ORA-06512: 在 "SYS.UTL_FILE", line 106
ORA-06512: 在 "SYS.UTL_FILE", line 746
ORA-06512: 在 line 12
文件读写中的异常处理
方法1
declare
--定义一个文件变量
f utl_file.file_type;
--声明一个字符串变量保存文件的一行记录
str varchar2(200);
begin
--打开文件
f:=utl_file.fopen('FILEPATH','2.txt','r');
loop
begin
--读取文件的一行记录
utl_file.get_line(f,str);
exception
when no_data_found then
exit;
end;
--打印str的值
dbms_output.put_line(str);
end loop;
--关闭文件
utl_file.fclose(f);
end;
方法2
declare
--定义一个文件变量
f utl_file.file_type;
--声明一个字符串变量保存文件的一行记录
str varchar2(200);
begin
--打开文件
f:=utl_file.fopen('FILEPATH','2.txt','r');
begin
loop
utl_file.get_line(f,str);
--打印str的值
dbms_output.put_line(str);
end loop;
exception
when no_data_found then
NULL; --占位
end;
--关闭文件
utl_file.fclose(f);
end;