0
点赞
收藏
分享

微信扫一扫

Postgresql和Oracle异常处理的异同

彭维盛 2022-03-30 阅读 58

exception内核改造简单研究。

PG

1 实例

PG只支持预定义异常的处理,即异常code都是定义好的,触发后走EXCEPTION部分代码逻辑。

DROP TABLE db;
CREATE TABLE db (a INT PRIMARY KEY, b TEXT);

CREATE OR REPLACE FUNCTION merge_db(key INT, data TEXT) RETURNS VOID AS
$$
DECLARE
  text_var1 text;
  text_var2 text;
  text_var3 text;
BEGIN
    LOOP
        BEGIN
            INSERT INTO db(a,b) VALUES (key, data);
            RETURN;
        EXCEPTION WHEN unique_violation THEN
             GET STACKED DIAGNOSTICS text_var1 = MESSAGE_TEXT, text_var2 = PG_EXCEPTION_DETAIL, text_var3 = PG_EXCEPTION_HINT;
             RAISE NOTICE E'MESSAGE_TEXT: %\n', text_var1;
             RAISE NOTICE E'PG_EXCEPTION_DETAIL: %\n', text_var2;
             RAISE NOTICE E'PG_EXCEPTION_HINT: %\n', text_var3;
             RETURN;
        END;
    END LOOP;
END;
$$
LANGUAGE plpgsql;

SELECT merge_db(1, 'david');
SELECT merge_db(1, 'dennis');

postgres=# SELECT merge_db(1, 'dennis');
NOTICE:  MESSAGE_TEXT: duplicate key value violates unique constraint "db_pkey"

NOTICE:  PG_EXCEPTION_DETAIL: Key (a)=(1) already exists.

NOTICE:  PG_EXCEPTION_HINT: 

 merge_db 
----------
 
(1 row)

2 PG异常处理语法

https://www.postgresql.org/docs/14/plpgsql-control-structures.html

[ <<label>> ]
[ DECLARE
    declarations ]
BEGIN
    statements
EXCEPTION
    WHEN condition [ OR condition ... ] THEN
        handler_statements
    [ WHEN condition [ OR condition ... ] THEN
          handler_statements
      ... ]
END;
  • 其中condition在这里查阅:
    https://www.postgresql.org/docs/14/errcodes-appendix.html

  • 支持两种形式的写法:
    WHEN division_by_zero THEN ...
    WHEN SQLSTATE '22012' THEN ...

Oracle

oracle支持三种异常形式:
在这里插入图片描述

https://docs.oracle.com/cd/E11882_01/timesten.112/e21639/exceptions.htm#TTPLS195

  • 第一种Predefined TimesTen error是和PG概念相同的。可以直接迁移。
  • 后两种需要PG代码改造实现。

1 预定义异常处理实例

SQL触发一些已经定义好的异常

Command> DECLARE v_invalid PLS_INTEGER;
       > BEGIN
       >   v_invalid := 100/0;
       > EXCEPTION
       > WHEN ZERO_DIVIDE THEN
       >   DBMS_OUTPUT.PUT_LINE ('Attempt to divide by 0');
       > END;
       > /
Attempt to divide by 0
 
PL/SQL procedure successfully completed.

2 用户定义异常处理实例

代码中主动raise,跳转到异常逻辑继续执行

Command> DECLARE
       >   v_deptno NUMBER := 500;
       >   v_name VARCHAR2 (20) := 'Testing';
       >   e_invalid_dept EXCEPTION;
       >  BEGIN
       >   UPDATE departments
       >   SET department_name = v_name
       >   WHERE department_id = v_deptno;
       >  IF SQL%NOTFOUND THEN
       >     RAISE e_invalid_dept;
       >  END IF;
       >  ROLLBACK;
       >  EXCEPTION
       >    WHEN e_invalid_dept THEN
       >    DBMS_OUTPUT.PUT_LINE ('No such department');
       >    DBMS_OUTPUT.PUT_LINE (SQLERRM);
       >    DBMS_OUTPUT.PUT_LINE (SQLCODE);
       > END;
       > /
No such department
User-Defined Exception
1
 
PL/SQL procedure successfully completed.
 
The command succeeded.

3 非预定义异常处理

出现一个异常后,将异常CODE和自定义异常名字关联起来,触发后直接进入定义好的处理逻辑。

步骤

-- 定义
<异常情况>  EXCEPTION;

-- 与标准的ORACLE错误联系起来
PRAGMA EXCEPTION_INIT(<异常情况>, <错误代码>);

-- 处理

实例

DECLARE
   deadlock_detected EXCEPTION;
   PRAGMA EXCEPTION_INIT(deadlock_detected, -60);
BEGIN
   NULL; -- Some operation that causes an ORA-00060 error
EXCEPTION
   WHEN deadlock_detected THEN
      NULL; -- handle the error
END;
/

实例2

INSERT INTO departments VALUES(50, 'FINANCE', 'CHICAGO');

DECLARE
   v_deptno departments.department_id%TYPE := &deptno;
   deptno_remaining EXCEPTION;
   PRAGMA EXCEPTION_INIT(deptno_remaining, -2292);
   /* -2292 是违反一致性约束的错误代码 */
BEGIN
   DELETE FROM departments WHERE department_id = v_deptno;
EXCEPTION
   WHEN deptno_remaining THEN 
      DBMS_OUTPUT.PUT_LINE('违反数据完整性约束!');
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;

https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/errors.htm#i1863

举报

相关推荐

0 条评论