ORACLE 异常错误处理
预定义错误:ORACLE提供了大约24种预定义错误,这些错误无需程序中手动定义,ORACLE会自动触发异常处理。 非预定义错误:这些是标准的ORACLE错误,需要程序中手动定义处理。 用户定义错误:程序员自定义的异常情况,需要显式触发。
在定义部分定义异常情况: 使用 在异常处理部分对异常情况进行处理。 如果当前块定义了异常处理,执行相应处理,程序继续执行。 如果没有定义处理,异常传播到包含块处理。
发布日期:2025-04-29 13:39:47
浏览次数:20
分类:精选文章
本文共 3177 字,大约阅读时间需要 10 分钟。
异常处理是PL/SQL程序中处理未预料事件的核心机制。以下是对异常处理的详细分析和实践指南。
5.1 异常处理概念
程序运行过程中,可能会遇到各种异常情况。这些异常可以分为以下几类:
5.1.1 预定义异常处理
预定义异常处理是ORACLE为程序自动提供的错误类型。常见的预定义错误包括:
| 错误号 | 错误信息 | 说明 |
|---|---|---|
| ORA-0001 | Dup_val_on_index | 违反了唯一性限制 |
| ORA-0051 | Timeout-on-resource | 等待资源时发生超时 |
| ORA-1001 | Invalid-CURSOR | 试图使用无效的游标 |
| ORA-1422 | Too_many_rows | SELECT INTO返回多行 |
| ORA-1476 | Zero-divide | 试图被零除 |
| ORA-1722 | Invalid-NUMBER | 转换数字失败 |
| ORA-6500 | Storage-error | 内存不足引发的内部错误 |
| ORA-6501 | Program-error | 内部错误 |
| ORA-6502 | Value-error | 转换或截断错误 |
| ORA-6511 | CURSOR-already-OPEN | 试图打开已打开的游标 |
| ORA-6530 | Access-INTO-null | 试图为null对象赋值 |
| ORA-6531 | Collection-is-null | 集合方法应用于null表或varray |
| ORA-6532 | Subscript-outside-limit | 索引引用超出范围 |
| ORA-6533 | Subscript-beyond-count | 索引引用大于集合元素个数 |
| ORA-6510 | Resource-exhausted | 资源耗尽 |
这些预定义错误可以直接引用其错误代码进行处理。
5.1.2 非预定义异常处理
对于非预定义错误,需要在程序中手动定义异常情况并与ORACLE错误关联。步骤如下:
EXCEPTIONWHEN exception_name THEN
PRAGMA EXCEPTION_INIT 将异常情况与错误代码关联:PRAGMA EXCEPTION_INIT(exception_name, error_code);
5.1.3 用户自定义异常处理
用户定义异常通过 RAISE 语句显式触发。例如:
RAISE my_exception;
当异常被触发时,控制转移到异常处理部分,执行相应的错误处理代码。
5.1.4 用户定义的异常处理
可以使用 RAISE_APPLICATION_ERROR 函数重新定义异常错误消息。语法如下:
RAISE_APPLICATION_ERROR(error_number, error_message, [keep_errors]);
error_number 范围在 -20000 到 -20999 之间,error_message 最多 2048 字节,keep_errors 为可选参数。
5.2 异常错误传播
异常错误可以在声明部分或执行部分引发,影响不同块的执行。
5.2.1 执行部分引发异常错误
当异常错误在执行部分引发时:
5.2.2 声明部分引发异常错误
如果声明部分引发异常错误,可能会影响其他块。例如:
BEGIN DECLARE name varchar2(12) := 'EricHu'; BEGIN EXCEPTION WHEN OTHERS THEN raise another_exception; END; END;EXCEPTION WHEN OTHERS THEN raise another_exception;END;
如果 name 为 NULL,虽然 EXCEPTION 块中有 WHEN OTHERS 处理,但由于错误在声明部分,WHEN OTHERS 不会被执行。
5.3 异常错误处理编程
在编程时,建议使用异常处理以避免程序终止。例如:
DECLARE v_sal number(7,2);BEGIN SELECT salary INTO v_sal FROM employees WHERE employee_id = v_empno; IF v_sal <= 1500 THEN UPDATE employees SET salary = salary + 100 WHERE employee_id = v_empno; DBMS_OUTPUT.PUT_LINE('编码为'||v_empno||'员工工资已更新!'); ELSE DBMS_OUTPUT.PUT_LINE('编码为'||v_empno||'员工工资已经超过规定值!'); END IF;EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('数据库中没有编码为'||v_empno||'的员工'); WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE('程序运行错误!请使用游标'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLCODE || '---' || SQLERRM);END; 5.4 使用 SQLCODE 和 SQLERRM
SQLCODE 返回遇到的 Oracle 错误号,SQLERRM 返回错误信息。例如:
- SQLCODE = -100,SQLERRM = 'no_data_found'
- SQLCODE = 0,SQLERRM = 'normal, successful completion'
5.5 使用 RAISE_APPLICATION_ERROR 存入错误信息
CREATE TABLE errors (errnum number(4), errmsg varchar2(100));DECLARE err_msg varchar2(100);BEGIN FOR err_num IN -100 .. 0 LOOP err_msg := SQLERRM(err_num); INSERT INTO errors VALUES (err_num, err_msg); END LOOP;END;
5.6 使用 RAISE_APPLICATION_ERROR 阻止错误
CREATE OR REPLACE TRIGGER tr_insert_empBEFORE INSERT ON employeesFOR EACH ROWBEGIN IF :new.first_name IS NULL OR :new.last_name IS NULL THEN RAISE_APPLICATION_ERROR(-20000, 'Employee must have a name.'); END IF;END;
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2026年06月21日 18时34分29秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
php实现上传(多个)文件函数封装
2023-03-01
php实现下载文件方法
2023-03-01
php实现单链表
2023-03-01
php实现图片背景换色功能
2023-03-01
php实现多个一维数组对应合并成二维数组
2023-03-01
php实现多关键字查找方法
2023-03-01
PHP实现微信公众号H5支付
2023-03-01
PHP实现微信公众号网页授权
2023-03-01
PHP实现微信小程序推送消息至公众号
2023-03-01
rabbitmq逻辑与开发
2023-03-01
php实现根据身份证获取年龄
2023-03-01
PHP实现的MongoDB数据增删改查
2023-03-01
PHP实现的SSO单点登录系统,拿走就用吧
2023-03-01
php实现短信验证功能
2023-03-01
php实现逆转数组
2023-03-01
PHP实现通过geoip获取IP地理信息
2023-03-01
PHP实现页面静态化、纯静态化及伪静态化
2023-03-01
php容许ajax跨域,PHP设置允许ajax跨域请求的两种常见方法
2023-03-01
RabbitMQ进程结构分析与性能调优
2023-03-01