PL/SQL 异常以啥顺序引发?

Posted

技术标签:

【中文标题】PL/SQL 异常以啥顺序引发?【英文标题】:In what order do PL/SQL Exceptions get raised?PL/SQL 异常以什么顺序引发? 【发布时间】:2019-07-13 01:14:34 【问题描述】:

我试图了解引发 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.

这是否有逻辑,还是不可能知道首先引发哪个异常?

编辑 乔恩·海勒是对的。 UPDATE 语句不会导致异常,因为WHERE 子句过滤掉了所有记录。我搞砸了太久了。无论如何,要点是 PL/SQL 异常根据它们发生的顺序引发,这很直观。很高兴知道。谢谢,乔恩。

【问题讨论】:

【参考方案1】:

PL/SQL 异常的引发取决于它们发生的顺序,而不是它们在EXCEPTION 子句中的顺序。

UPDATE 语句不得引发异常。 (如果您确定是,那么如果您使用minimal, reproducible example 修改问题,我们可以解决。

另外,与问题没有直接关系,但我建议删除您的自定义异常处理。它没有提供任何有价值的东西。如果没有异常处理,该块将自动引发错误消息、对象名称和行号,这是调试问题的大量信息。使用您的自定义异常处理,对象名称和行号不存在。如果未启用 DBMS_OUTPUT,则不会出现异常。

【讨论】:

以上是关于PL/SQL 异常以啥顺序引发?的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL 异常不会引发

引发异常后 PL/SQL 继续

为啥在匿名 PL/SQL 块中没有立即引发异常?

约束违反异常 PL/SQL

PL SQL 过程不引发异常 no_data_found

PL/SQL预定义异常