本文共 3177 字,大约阅读时间需要 10 分钟。
异常处理是PL/SQL程序中处理未预料事件的核心机制。以下是对异常处理的详细分析和实践指南。
程序运行过程中,可能会遇到各种异常情况。这些异常可以分为以下几类:
预定义异常处理是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 | 资源耗尽 |
这些预定义错误可以直接引用其错误代码进行处理。
对于非预定义错误,需要在程序中手动定义异常情况并与ORACLE错误关联。步骤如下:
EXCEPTIONWHEN exception_name THEN
PRAGMA EXCEPTION_INIT 将异常情况与错误代码关联:PRAGMA EXCEPTION_INIT(exception_name, error_code);
用户定义异常通过 RAISE 语句显式触发。例如:
RAISE my_exception;
当异常被触发时,控制转移到异常处理部分,执行相应的错误处理代码。
可以使用 RAISE_APPLICATION_ERROR 函数重新定义异常错误消息。语法如下:
RAISE_APPLICATION_ERROR(error_number, error_message, [keep_errors]);
error_number 范围在 -20000 到 -20999 之间,error_message 最多 2048 字节,keep_errors 为可选参数。
异常错误可以在声明部分或执行部分引发,影响不同块的执行。
当异常错误在执行部分引发时:
如果声明部分引发异常错误,可能会影响其他块。例如:
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 不会被执行。
在编程时,建议使用异常处理以避免程序终止。例如:
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; SQLCODE 返回遇到的 Oracle 错误号,SQLERRM 返回错误信息。例如:
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;
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;
转载地址:http://expfk.baihongyu.com/