前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Postgresql中plpgsql异常处理方法与实例(RAISE EXCEPTION)

Postgresql中plpgsql异常处理方法与实例(RAISE EXCEPTION)

作者头像
mingjie
发布2022-09-26 21:55:39
3K0
发布2022-09-26 21:55:39
举报

Postgresql中有关plpgsql异常处理的一切(RAISE EXCEPTION)

1 抛出异常

主要列出实例,语法比较简单

语法

现在PL中支持使用RAISE语法抛出异常,具体支持下面五种语法:

代码语言:javascript
复制
1 RAISE [ level ] 'format' [, expression [, ... ]] [ USING option = expression [, ... ] ];
2 RAISE [ level ] condition_name [ USING option = expression [, ... ] ];
3 RAISE [ level ] SQLSTATE 'sqlstate' [ USING option = expression [, ... ] ];
4 RAISE [ level ] USING option = expression [, ... ];
5 RAISE ; -- 特殊,只能在EXCEPTION语法块中使用,重新抛出catch的异常。
  • level
    • 可选DEBUG, LOG, INFO, NOTICE, WARNING, EXCEPTION
    • 其中DEBUGWARNING都不会产生错误,只会打印日志,日志级别按level输出,由log_min_messages、client_min_messages参数决定是否输出。
    • 其中EXCEPTION会产生错误,中断程序执行,错误如果不被捕获会被抛到上一层。
  • 抛出指定类型的异常
    • 方式一:RAISE SQLSTATE
    • 方式二:RAISE condition_name
    • 方式三:RAISE 'text' USING ERRCODE = 'unique_violation'

抛出异常的实例展示

文本拼接

代码语言:javascript
复制
do $g$
DECLARE
  v_job_id int := 100;
BEGIN
  RAISE NOTICE 'Calling cs_create_job(%)', v_job_id;
END;
$g$;

执行结果

代码语言:javascript
复制
postgres=# do $g$
postgres$# DECLARE
postgres$#   v_job_id int := 100;
postgres$# BEGIN
postgres$#   RAISE NOTICE 'Calling cs_create_job(%)', v_job_id;
postgres$# END;
postgres$# $g$;
NOTICE:  Calling cs_create_job(100)
DO

使用Hint

级别可任选,这里使用EXCEPTION没人处理,所以抛到顶层报错。

代码语言:javascript
复制
do $g$
DECLARE
  user_id int := 100;
BEGIN
  RAISE EXCEPTION 'Nonexistent ID --> %', user_id
      USING HINT = 'Please check your user ID';
END;
$g$;

执行结果

代码语言:javascript
复制
postgres=# do $g$
postgres$# DECLARE
postgres$#   user_id int := 100;
postgres$# BEGIN
postgres$#   RAISE EXCEPTION 'Nonexistent ID --> %', user_id
postgres$#       USING HINT = 'Please check your user ID';
postgres$# END;
postgres$# $g$;
ERROR:  Nonexistent ID --> 100
HINT:  Please check your user ID
CONTEXT:  PL/pgSQL function inline_code_block line 5 at RAISE

抛出指定类型异常

1

代码语言:javascript
复制
do $g$
DECLARE
  user_id int := 100;
BEGIN
  RAISE 'Duplicate user ID: %', user_id USING ERRCODE = 'unique_violation';
END;
$g$;

-- ERROR:  Duplicate user ID: 100
-- CONTEXT:  PL/pgSQL function inline_code_block line 5 at RAISE

2

代码语言:javascript
复制
do $g$
DECLARE
  user_id int := 100;
BEGIN
  RAISE 'Duplicate user ID: %', user_id USING ERRCODE = '23505';
END;
$g$;

-- ERROR:  Duplicate user ID: 100
-- CONTEXT:  PL/pgSQL function inline_code_block line 1 at RAISE

3

代码语言:javascript
复制
do $g$
BEGIN
  RAISE division_by_zero;
END;
$g$;

-- ERROR:  division_by_zero
-- CONTEXT:  PL/pgSQL function inline_code_block line 3 at RAISE

4

代码语言:javascript
复制
do $g$
BEGIN
  RAISE SQLSTATE '22012';
END;
$g$;

-- ERROR:  22012
-- CONTEXT:  PL/pgSQL function inline_code_block line 3 at RAISE

5

代码语言:javascript
复制
do $g$
DECLARE
  user_id int := 100;
BEGIN
  RAISE unique_violation USING MESSAGE = 'Duplicate user ID: ' || user_id;
END;
$g$;

-- ERROR:  Duplicate user ID: 100
-- CONTEXT:  PL/pgSQL function inline_code_block line 5 at RAISE

2 捕获处理异常

捕获&&处理异常

语法

代码语言:javascript
复制
[ <<label>> ]
[ DECLARE
    declarations ]
BEGIN
    statements
EXCEPTION
    WHEN condition [ OR condition ... ] THEN
        handler_statements
    [ WHEN condition [ OR condition ... ] THEN
          handler_statements
      ... ]
END;

在EXCEPTION内的特殊变量:
- SQLSTATE
- SQLERRM
  • condition:异常名字,有两种使用方式,所有异常列表在PG文档中可以找到《Appendix A. PostgreSQL Error Codes》,下面列举一部分。
    • 异常名:WHEN division_by_zero THEN规律:小写下划线连接关键字
    • 异常码:WHEN SQLSTATE '22012' THEN ...规律:5位字符,数字和任意字母组成
    • OTHERS:匹配一些异常
  • handler_statements:异常处理语法块,如果这里面再产生异常不会被当前的EXCEPTION捕获,会直接抛到上层。
  • 特殊变量:SQLSTATE、SQLERRM只在EXCEPTION语法块中生效,可以打印错误码和错误信息。
    • 例如:division_by_zero异常处理时,sqlerrm="division by zero"sqlstate=22012

部分condition实例

代码语言:javascript
复制
Class 00 — Successful Completion
  00000	successful_completion

Class 01 — Warning
  01000	warning
  0100C	dynamic_result_sets_returned
  01008	implicit_zero_bit_padding
  01003	null_value_eliminated_in_set_function
  01007	privilege_not_granted
  01006	privilege_not_revoked
  01004	string_data_right_truncation
  01P01	deprecated_feature

Class 22 — Data Exception
  22000	data_exception
  2202E	array_subscript_error
  22021	character_not_in_repertoire
  22008	datetime_field_overflow
  22012	division_by_zero
  22005	error_in_assignment
  2200B	escape_character_conflict
  22022	indicator_overflow
  22015	interval_field_overflow

异常捕获实例

1 系统异常

代码语言:javascript
复制
do $g$
DECLARE
  user_id int := 100;
BEGIN
  user_id = user_id / 0;
EXCEPTION
    WHEN division_by_zero THEN
        RAISE NOTICE 'caught division_by_zero';
END;
$g$;

-- NOTICE:  caught division_by_zero

2 主动产生异常:没给错误码使用SQLSTATE P0001

没显示指定错误码,使用P0001、raise_exception:

代码语言:javascript
复制
do $g$
DECLARE
  user_id int := 100;
  text_var1 text;
  text_var2 text;
  text_var3 text;
  text_var4 text;
  text_var5 text;
BEGIN
  RAISE EXCEPTION 'Nonexistent ID --> %', user_id USING HINT = 'Please check your user ID';
EXCEPTION 
  WHEN OTHERS THEN
    GET STACKED DIAGNOSTICS text_var1 = MESSAGE_TEXT,
                            text_var2 = PG_EXCEPTION_DETAIL,
                            text_var3 = PG_EXCEPTION_HINT,
                            text_var4 = PG_EXCEPTION_CONTEXT,
                            text_var5 = RETURNED_SQLSTATE;
    raise notice '%', text_var1;
    raise notice '%', text_var2;
    raise notice '%', text_var3;
    raise notice '%', text_var4;
    raise notice '%', text_var5;
END;
$g$;

-- NOTICE:  Nonexistent ID --> 100
-- NOTICE:  
-- NOTICE:  Please check your user ID
-- NOTICE:  PL/pgSQL function inline_code_block line 10 at RAISE
-- NOTICE:  P0001

3 主动抛出异常:给定错误码

代码语言:javascript
复制
do $g$
DECLARE
  user_id int := 100;
  text_var1 text;
  text_var2 text;
  text_var3 text;
  text_var4 text;
  text_var5 text;
BEGIN
  RAISE 'Duplicate user ID: %', user_id USING ERRCODE = 'unique_violation';
EXCEPTION 
  WHEN OTHERS THEN
    GET STACKED DIAGNOSTICS text_var1 = MESSAGE_TEXT,
                            text_var2 = PG_EXCEPTION_DETAIL,
                            text_var3 = PG_EXCEPTION_HINT,
                            text_var4 = PG_EXCEPTION_CONTEXT,
                            text_var5 = RETURNED_SQLSTATE;
    raise notice '%', text_var1;
    raise notice '%', text_var2;
    raise notice '%', text_var3;
    raise notice '%', text_var4;
    raise notice '%', text_var5;
END;
$g$;

-- NOTICE:  Duplicate user ID: 100
-- NOTICE:  
-- NOTICE:  
-- NOTICE:  PL/pgSQL function inline_code_block line 10 at RAISE
-- NOTICE:  23505

4 特殊变量:注意sqlerrm会被异常文本替换掉,sqlstate永远是预定义好的错误码

代码语言:javascript
复制
do $g$
DECLARE
  user_id int := 100;
BEGIN
  RAISE EXCEPTION 'Nonexistent ID --> %', user_id USING HINT = 'Please check your user ID';
EXCEPTION 
  WHEN OTHERS THEN
    raise notice 'sqlstate: %', sqlstate;
    raise notice 'sqlerrm: %', sqlerrm;
END;
$g$;

-- NOTICE:  sqlstate: P0001
-- NOTICE:  sqlerrm: Nonexistent ID --> 100
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-09-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 抛出异常
    • 语法
      • 抛出异常的实例展示
        • 文本拼接
        • 使用Hint
        • 抛出指定类型异常
    • 2 捕获处理异常
      • 语法
        • 异常捕获实例
          • 1 系统异常
          • 2 主动产生异常:没给错误码使用SQLSTATE P0001
          • 3 主动抛出异常:给定错误码
          • 4 特殊变量:注意sqlerrm会被异常文本替换掉,sqlstate永远是预定义好的错误码
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档