以美元符号作为引号的字符串常量
本章将讨论如何在 PL/pgSQL 编程中使用以美元符号作为引号的字符串常量。块结构
本章将讨论 PL/pgSQL 的块结构,同时也会带你编写第一个 PL/pgSQL 程序。变量
本章将学习 PL/pgSQL 变量的相关知识。行类型
本章将讨论 PL/pgSQL 的行类型。将一个变量声明为行类型之后,它便可以保存数据库中的整行数据。记录类型
本章我们讨论 PostgreSQL 的记录类型,它和行类型相似,也可以存储数据库中的整行信息。常量
本章将讨论 PL/pgSQL 常量。错误和异常处理
本章我们将讨论 PL/pgSQL 的错误和异常处理。控制结构
本章将讨论 PL/pgSQL 的控制结构,包括:IF、CASE、LOOP、WHILE LOOP、FOR LOOP、EXIT和CONTINUE等语句。函数
本章我们将讨论自定义函数的相关知识,包括:创建函数、函数参数的模式、函数重载、返回表的函数以及删除函数等知识。存储过程
本章我们将讨论存储过程。游标
本章我们将讨论 PL/pgSQL 的游标以及如何使用它们逐行处理结果集。触发器
本章将讨论触发器,包括:创建、删除、更新、禁用、启用触发器等知识。
错误和异常处理
- 416
- 2023-08-01 09:18:09
本章我们将讨论 PL/pgSQL 的错误和异常处理。
报告消息
raise 级别 格式;
级别
:指定严重性,可选值为:debug
log
notice
info
warning
exception
(默认值)
格式
:消息的字符串,其中的占位符%
将被参数的值替换- 占位符的数量必须和参数的数量一致
- 占位符的数量必须和参数的数量一致
以下示例演示了不同级别下,显示当前时间的消息:
抛出错误
使用 raise exception
即可抛出错误,这也是 raise
的默认级别(如果没有提供 级别
参数的话)。
raise
还可以使用以下可选子句来附加更多信息:
USING 选项 = 表达式;
选项
的可选值有:
message
:设置错误消息hint
:提供提示信息,以便容易定位错误detail
:给出有关错误的详细信息errcode
:错误代码
以下示例抛出邮箱重复的错误:
do $$
declare
email varchar(255) := '[email protected]';
begin
-- 检查邮箱是否重复
-- ...
-- 报告邮箱重复
raise exception '邮箱重复:%', email
using hint = '请检查邮箱地址';
end $$;
断言
ASSERT
语句是将调试检查插入到 PL/pgSQL 的实用的简便方法。语法如下:
assert 条件 [, 提示信息];
条件
:是一个布尔表达式,预期返回TRUE
。如果它的计算结果为TRUE
,则ASSERT
不执行任何操作;否则(NULL
或FALSE
),会引发assert_failure
异常提示信息
:可选参数。如果不传递该参数,PostgreSQL 使用默认的assertion failed
消息;否则使用该参数作为提示信息。
assert
应该只用于检测错误,而不是报告错误。如果要报告错误,应使用raise
assert
应该只用于检测错误,而不是报告错误。如果要报告错误,应使用 raise
通过 plpgsql.check_asserts
配置来启用或关闭断言。如果将该配置项设置为 off
,将关闭断言。
以下示例使用 assert
来检查示例数据中 film
表是否有数据:
do $$
declare
film_count integer;
begin
select count(*)
into film_count
from film;
assert film_count > 0, '没有影片';
end$$;
异常处理
当块中发生错误时,PostgreSQL 将中止该块及周围事务的执行。要从错误中恢复,可以在 BEGIN...END
块中使用 EXCEPTION
子句。
其语法如下:
<<label>>
declare
begin
statements;
exception
when condition [or condition...] then
handle_exception;
[when condition [or condition...] then
handle_exception;]
[when others then
handle_other_exceptions;
]
end;
以下示例会发生错误,因为 ID 为 2000 的电影不存在,它会抛出 no_data_found
异常。通过使用 EXCEPTION
捕获后,进行更有意义的处理:
do $$
declare
rec record;
v_film_id int = 2000;
begin
select film_id, title
into strict rec
from film
where film_id = v_film_id;
-- 捕获异常
exception
when no_data_found then
raise exception '电影 % 不存在', v_film_id;
end $$;
以下示例演示了如何处理 too_mary_rows
异常:
do $$
declare
rec record;
begin
select film_id, title
into strict rec
from film
where title LIKE 'A%';
exception
when too_many_rows then
raise exception '查询结果返回多行';
end $$;
以下示例演示了如何捕获多个异常:
do $$
declare
rec record;
v_length int = 90;
begin
select film_id, title
into strict rec
from film
where length = v_length;
exception
when sqlstate 'P0002' then
raise exception 'film with length % not found', v_length;
when sqlstate 'P0003' then
raise exception 'The with length % is not unique', v_length;
end $$;