添加外键关联:
ALTER TABLE dept_learn ADD CONSTRAINT pk_dept_deptid PRIMARY KEY (department_id);
ALTER TABLE emp_learn ADD CONSTRAINT fk_emp_dept_deptid FOREIGN KEY (department_id) REFERENCES dept_learn(department_id);
在PL/SQL块中捕获并处理异常,可以提高程序的健壮性,使得应用程序可以安全正常的运行。异常是一种PL/SQL标识符,它有预定义异常、非预定义异常和自定义异常三种类型。在PL/SQL块中,如果不捕获和处理异常,oracle会将错误传递到调用环境。
本节学习目标:
指由PL/SQL所提供的系统异常。oracle为开发人员提供了21个预定义异常(将在本节末尾一一列出),每个预定义异常对应一个特定的oracle错误,当PL/SQL块出现这些oracle错误时,会隐含的触发相应的预定义异常。
示例:
DECLARE
v_name emp_learn.first_name%TYPE;
BEGIN
SELECT first_name INTO v_name FROM emp_learn WHERE department_id = &dno;
dbms_output.put_line('雇员号'||&dno||'的名字为:'||v_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('不存在该部门!');
WHEN TOO_MANY_ROWS THEN
dbms_output.put_line('该部门有多个员工!');
WHEN OTHERS THEN
dbms_output.put_line('未知错误!');
END;
非预定义异常用于处理与预定义异常无关的oracle错误。预定义异常只能处理21种oracle错误,而PL/SQL块可能还会遭遇其它oracle错误,此时可能需要用到非预定义异常了。
非预定义异常使用步骤:
a)定义异常标识符。必须在定义部分定义异常标识符。
b)在oracle错误号和异常之间建立关联。需要在定义部分引用伪过程EXCEPTION_INIT。
c)捕捉并处理异常。
示例:在此节的开始时,我们为emp_learn和dept_learn变建立了外键关联,当更新雇员的部门号时,部门号必须在dept_learn表中存在,否则会触发ORA-02291错误。
-- 触发ORA-02291错误
SQL> UPDATE emp_learn SET department_id=2000 WHERE employee_id = 198;
ORA-02291: 违反完整约束条件 (HR.FK_EMP_DEPT_DEPTID) - 未找到父项关键字
-- 使用非预定义异常处理ora-02291错误
DECLARE
e_int EXCEPTION;
PRAGMA EXCEPTION_INIT(e_int,-2291);
v_name emp_learn.first_name%TYPE:=LOWER('&name');
v_deptno dept_learn.department_id%TYPE:=&dno;
BEGIN
UPDATE emp_learn SET department_id=v_deptno WHERE LOWER(first_name) = v_name;
EXCEPTION
WHEN e_int THEN
dbms_output.put_line('该部门不存在!');
END;
在上面“使用非预定义异常处理ora-02291错误”的示例代码中,如果输入一个不存在的雇员的first_name,将不会更新到行数据,不会触发e_int这个非预定义异常,PL/SQL将不会给出任何提示信息。如果此时需要获取到某些信息,或者做某些操作的话,就需要用到自定义异常了。
使用步骤:
a)定义异常标识符。必须在定义部分定义。
b)主动触发异常。使用RAISE语句显式触发。
c)捕获并处理异常。
示例:
DECLARE
e_int EXCEPTION;
e_int_norows EXCEPTION;
PRAGMA EXCEPTION_INIT(e_int,-2291);
v_name emp_learn.first_name%TYPE:=LOWER('&name');
v_deptno dept_learn.department_id%TYPE:=&dno;
BEGIN
UPDATE emp_learn SET department_id=v_deptno WHERE LOWER(first_name) = v_name;
IF SQL%NOTFOUND THEN
RAISE e_int_norows;
END IF;
EXCEPTION
WHEN e_int THEN
dbms_output.put_line('该部门不存在!');
WHEN e_int_norows THEN
dbms_output.put_line('该雇员不存在!');
END;
异常处理函数用于取得oracle错误号和错误消息,其中函数SQLCODE用于取得错误号,SQLERRM用于取得错误消息。当编写PL/SQL块时,通过在异常处理部分引用函数SQLCODE和SQLERRM,可以取得未预计到的oracle错误。通过使用内置过程RAISE_APPLICATION_ERROR,可以在建立子程序(过程、函数和包)时自定义错误号和错误消息。
RAISE_APPLICATION_ERROR过程只适用于数据库子程序(过程、函数、包、触发器),语法:
raise_application_error(error_number,message,[,{TRUE | FALSE}]);
当第三个参数设置为TRUE,则错误会存放到先前错误堆栈,否则会替换先前所有错误。
示例:
DECLARE
e_int EXCEPTION;
PRAGMA EXCEPTION_INIT(e_int,-20000);
BEGIN
DELETE FROM dept_learn WHERE department_id=&dno;
IF SQL%NOTFOUND THEN
raise_application_error(-20000,'该部门不存在!');
END IF;
EXCEPTION
WHEN e_int THEN
dbms_output.put_line('错误号:'||SQLCODE||',错误消息:'||SQLERRM);
WHEN OTHERS THEN
dbms_output.put_line('others-错误号:'||SQLCODE||',错误消息:'||SQLERRM);
END;