ON EXCEPTION 语句的放置

ON EXCEPTION 语句是一个声明性语句,不是可执行语句。出于此原因,ON EXCEPTION 必须在任何可执行语句之前并且在 SPL 中必须跟随任何 DEFINE 语句。

因为 SPL 例程的主体是语句块,所以 ON EXCEPTION 语句进程在例程的开头出现,并应用于例程的整个代码中。

语句示例显示了 ON EXCEPTION 语句的正确放置,以致于 FOREACH 语句在发生错误可以继续处理行。过程 X( ) 从表 A 读取客户编号,并将其插入到表 B。因为 INSERT 语句在 ON EXCEPTION 语句的作用域内,所以 INSERT 操作期间的错误会导致执行控制转移到 FOREACH 游标的下一行,而不用终止此 FOREACH 循环。
CREATE PROCEDURE X()
              
              DEFINE v_cust_num CHAR(20);
              
              FOREACH cs_insert FOR SELECT cust_num INTO v_cust_num FROM A
              BEGIN
              ON EXCEPTION
              END EXCEPTION WITH RESUME;
              INSERT INTO B(cust_num) VALUES(v_cust_num);
              END
              END FOREACH
              
              END PROCEDURE
下一示例中,函数 add_salesperson( ) 向表中插入一组值。如果表不存在,则先创建该表再插入值。该函数还返回表中的总行数:
CREATE FUNCTION add_salesperson(last CHAR(15), first CHAR(15))
              RETURNING INT;
              DEFINE x INT;
              ON EXCEPTION IN (-206) -- If no table was found, create one
              CREATE TABLE emp_list          
              (lname CHAR(15),fname CHAR(15), tele CHAR(12));
              INSERT INTO emp_list VALUES -- and insert values
              (last, first, '800-555-1234');
              END EXCEPTION WITH RESUME;
              INSERT INTO emp_list VALUES (last, first, '800-555-1234');
              SELECT count(*) INTO x FROM emp_list;
              RETURN x;
              END FUNCTION;

当出现错误时,数据库服务器搜索捕获错误代码的最后一个 ON EXCEPTION 语句。如果数据库服务器找不到相关 ON EXCEPTION 语句,则错误代码传回调用上下文(SPL 例程、应用程序或交互用户),执行终止。

在前面的示例中,在指定错误 -206 的 IN 子句中需要减号(-),大多数错误代码都是负整数。

下一示例使用了两个具有相同错误号的 ON EXCEPTION 语句,因而可以在两个嵌套级别中捕获错误代码 691 。除了标有 { 6 } 的 DELETE 语句,所有其它 DELETE 语句都在第一个 ON EXCEPTION 语句的作用域中。标有 { 1 }{ 2 } 的 DELETE 语句都在内部 ON EXCEPTION 语句的作用域中:
CREATE PROCEDURE delete_cust (cnum INT)
              ON EXCEPTION  IN (-691)    -- children exist
              BEGIN -- Begin-end so no other DELETEs get caught in here.
              ON EXCEPTION IN (-691)
              DELETE FROM another_child WHERE num = cnum;   { 1 }
              DELETE FROM orders WHERE customer_num = cnum; { 2 }
              END EXCEPTION -- for error -691
              DELETE FROM orders WHERE customer_num = cnum;    { 3 }
              END
              DELETE FROM cust_calls WHERE customer_num = cnum;   { 4 }
              DELETE FROM customer WHERE customer_num = cnum;     { 5 }
              END EXCEPTION
              DELETE FROM customer WHERE customer_num = cnum;        { 6 }
              END PROCEDURE