我正在尝试理解引发PL / SQL异常的顺序。这是我使用HR模式的代码:
DECLARE
dept_to_delete departments.department_id%TYPE := 105;
dept_to_keep departments.department_id%TYPE := 115;
integrity_constraint_violated EXCEPTION;
PRAGMA EXCEPTION_INIT(integrity_constraint_violated, -2291);
no_department_to_delete EXCEPTION;
BEGIN
-- Will cause integrity_constraint_violated error
UPDATE employees
SET department_id = dept_to_keep
WHERE department_id = dept_to_delete;
DELETE FROM departments
WHERE department_id = dept_to_delete;
IF SQL%NOTFOUND THEN
RAISE no_department_to_delete;
END IF;
EXCEPTION
WHEN integrity_constraint_violated THEN
DBMS_OUTPUT.PUT_LINE('Cannot assign employees to non-existing department.');
WHEN no_department_to_delete THEN
DBMS_OUTPUT.PUT_LINE('No such department to delete.');
END;
部门表中既没有部门ID 105也没有部门115。我的期望是首先引发integrity_contraint_violated
异常,因为它首先出现在代码中,但是用户定义的no_department_to_delete
首先被引发。输出为:
Cannot assign employees to non-existing department.
这是否有逻辑,还是不可能首先知道会引发哪个异常?
编辑
乔恩·海勒(Jon Heller)是对的。 UPDATE
语句不会引起异常,因为WHERE
子句会过滤掉所有记录。我搞砸了太久了。无论如何,可以得出的结论是, PL / SQL异常是根据它们发生的顺序而引发的,这很直观。很高兴知道。谢谢,乔恩。
答案 0 :(得分:4)
PL / SQL异常的产生取决于其发生的顺序,而不是它们在EXCEPTION
子句中的顺序。
UPDATE
语句一定不能引发异常。 (如果确定的话,那么如果您使用minimal, reproducible example修改问题,我们可以解决。
此外,与问题没有直接关系,但我建议删除自定义异常处理。它没有提供任何有价值的东西。如果没有异常处理,该块将自动引发错误消息,对象名称和行号,这是调试问题的大量信息。使用自定义异常处理时,不存在对象名称和行号。如果未启用DBMS_OUTPUT,则不会看到该异常。