您可以拦截某些类型的错误并在过程或触发器内处理,而不是将其传递回调用环境。这是通过使用异常处理程序完成的。
使用复合语句的 EXCEPTION 部分来定义异常处理程序。
只要在复合语句中发生错误,异常处理程序就会执行。与错误不同,警告不会导致执行异常处理代码。如果错误出现在嵌套的复合语句中,或者出现在复合语句内任何地方所调用的过程或触发器中,异常处理代码也会执行。
中断错误 SQL_INTERRUPT、SQLSTATE 57014 的异常处理程序应只包含不可中断的语句,如 ROLLBACK 和 ROLLBACK TO SAVEPOINT 等。如果异常处理程序包含连接中断时调用的可中断语句,数据库服务器将在第一个可中断语句处停止异常处理程序,并返回中断错误。
异常处理程序可以使用 SQLSTATE 或 SQLCODE 特殊值以确定语句失败的原因。也可以使用 ERRORMSG 函数(无需参数)返回与 SQLSTATE 相关的错误状况。只有每个 WHEN 子句中的第一个语句可以指定此信息,并且该语句不得为复合语句。
在此示例中,InnerProc 过程中的异常处理程序处理未找到列的错误。为进行演示,使用 SIGNAL 语句人为地生成错误。
OuterProc 过程中还包括异常处理程序。
CREATE OR REPLACE PROCEDURE OuterProc()
BEGIN
MESSAGE 'Hello from OuterProc' TO CLIENT;
CALL InnerProc();
MESSAGE 'SQLSTATE set to ', SQLSTATE,' in OuterProc (no exception)' TO CLIENT;
EXCEPTION
WHEN OTHERS THEN
MESSAGE 'SQLSTATE set to ', SQLSTATE,' in OuterProc (exception)' TO CLIENT;
RESIGNAL ;
END;
CREATE OR REPLACE PROCEDURE InnerProc()
BEGIN
DECLARE column_not_found EXCEPTION FOR SQLSTATE '52003';
MESSAGE 'Hello from InnerProc' TO CLIENT;
SELECT 'OK';
SIGNAL column_not_found;
MESSAGE 'SQLSTATE set to ', SQLSTATE,' in InnerProc (no exception)' TO CLIENT;
EXCEPTION
WHEN column_not_found THEN
MESSAGE 'SQLSTATE set to ', SQLSTATE, ' in InnerProc (exception)' TO CLIENT;
--RESIGNAL;
WHEN OTHERS THEN
RESIGNAL;
END;
CALL OuterProc();
使用 Interactive SQL 运行此示例时,[“结果”] 选项卡显示结果 [正常]。[“历史记录”] 选项卡显示以下内容:
Hello from OuterProc
Hello from InnerProc
SQLSTATE set to 52003 in InnerProc (exception)
SQLSTATE set to 00000 in OuterProc (no exception)
EXCEPTION 子句声明一个或多个异常处理程序的启动。EXCEPTION 后的各行直到错误发生时才会执行。每一 WHEN 子句都指定一个异常名称(用 DECLARE 语句声明)以及在遇到该异常时要执行的语句。
WHEN OTHERS THEN 子句指定当所发生的异常没有出现在之前的 WHEN 子句时要执行的语句。
在上述示例中,RESIGNAL 语句将该异常传递给更高级别的异常处理程序。如果未在异常处理程序中指定 WHEN OTHERS THEN,则所有未处理异常的缺省操作均为 RESIGNAL。
为将 column_not_found 异常传入 OuterProc,请将注释指示符从 RESIGNAL 语句中移除。这将调用 OuterProc 过程中的异常处理程序。
EXCEPTION 处理程序,而不是执行 SIGNAL 语句之后的那些行。
ON EXCEPTION RESUME 与显式异常处理一起使用。如果包括 ON EXCEPTION RESUME,将不会执行异常处理代码。