PRAGMA EXCEPTION_INIT将用户定义的错误代码与异常相关联。PRAGMA EXCEPTION_INIT声明可包含在任何块、子块或包中。只能在声明异常后将错误代码分配给该异常(使用PRAGMA EXCEPTION_INIT)。

PRAGMA EXCEPTION_INIT声明的格式如下:

PRAGMA EXCEPTION_INIT(exception_name,
                      {exception_number | exception_code})

其中:

  • exception_name是关联异常的名称。
  • Exception_number是用户定义的错误代码,与pragma关联。如果您指定未映射的exception_number,服务器将返回一条警告。
  • Exception_code是预定义异常的名称。有关有效异常的完整列表,请参见Postgres 核心文档

用户定义的异常提供了一个示例,其中演示了如何在包中声明用户定义的异常。以下示例使用了相同的基本结构,但新增了PRAGMA EXCEPTION_INIT声明:

CREATE OR REPLACE PACKAGE ar AS
  overdrawn EXCEPTION;
  PRAGMA EXCEPTION_INIT (overdrawn, -20100);
  PROCEDURE check_balance(p_balance NUMBER, p_amount NUMBER);
END;

CREATE OR REPLACE PACKAGE BODY ar AS
   PROCEDURE check_balance(p_balance NUMBER, p_amount  NUMBER)
   IS
   BEGIN
       IF (p_amount > p_balance) THEN
         RAISE overdrawn;
       END IF;
    END;

以下存储过程 (purchase) 调用check_balance存储过程。如果p_amount大于p_balance,则check_balance会引发异常;purchase会捕获ar.overdrawn异常。

CREATE PROCEDURE purchase(customerID int, amount NUMERIC)
AS
  BEGIN
     ar.check_ balance(getcustomerbalance(customerid), amount);
       record_purchase(customerid, amount);
  EXCEPTION
     WHEN ar.overdrawn THEN
      DBMS_OUTPUT.PUT_LINE ('This account is overdrawn.');
      DBMS_OUTPUT.PUT_LINE ('SQLCode :'||SQLCODE||' '||SQLERRM );
END;

当ar.check_balance引发异常时,执行会跳到purchase中定义的异常处理程序。

EXCEPTION
     WHEN ar.overdrawn THEN
      DBMS_OUTPUT.PUT_LINE ('This account is overdrawn.');
      DBMS_OUTPUT.PUT_LINE ('SQLCode :'||SQLCODE||' '||SQLERRM );

该异常处理程序会返回一条错误消息,后跟SQLCODE信息:

This account is overdrawn.
SQLCODE: -20100 User-Defined Exception

以下示例演示了如何使用预定义的异常。代码为no_data_found异常创建了一个更有意义的名称;如果给定的客户不存在,代码会捕获异常,调用DBMS_OUTPUT.PUT_LINE以报告错误,然后重新引发原始异常:

CREATE OR REPLACE PACKAGE ar AS
  overdrawn EXCEPTION;
  PRAGMA EXCEPTION_INIT (unknown_customer, no_data_found);
  PROCEDURE check_balance(p_customer_id NUMBER);
END;

CREATE OR REPLACE PACKAGE BODY ar AS
   PROCEDURE check_balance(p_customer_id NUMBER)
   IS
   DECLARE
     v_balance NUMBER;
   BEGIN
     SELECT balance INTO v_balance FROM customer
       WHERE cust_id = p_customer_id;
   EXCEPTION WHEN unknown_customer THEN
     DBMS_OUTPUT.PUT_LINE('invalid customer id');
     RAISE;
   END;