抛出错误语句
介绍PL/SQL中修改和抛出错误的语句signal和resignal语句。
SIGNAL语句
signal语句可以在存储过程中向调用者返回错误或警告条件,语法如下:
SIGNAL condition_value
[SET signal_information_item
[, signal_information_item] ...]
condition_value: {
SQLSTATE [VALUE] sqlstate_value
| condition_name
}
signal_information_item:
condition_information_item_name = simple_value_specification
condition_information_item_name: {
CLASS_ORIGIN
| SUBCLASS_ORIGIN
| MESSAGE_TEXT
| MYSQL_ERRNO
| CONSTRAINT_CATALOG
| CONSTRAINT_SCHEMA
| CONSTRAINT_NAME
| CATALOG_NAME
| SCHEMA_NAME
| TABLE_NAME
| COLUMN_NAME
| CURSOR_NAME
}
SIGNAL可以抛出一个SQLSTATE值(SQLSTATE [VALUE] sqlstate_value)或命名(condition_name)的错误条件,SET子句可以设置不同的信息,SET子句中设置的信息可以通过GET DIAGNOSTICS语句获取。
参数说明:
- condition_value表示要返回的错误值,该值可以是SQLSTATE值,也可以是condition_name(declare … condition语法声明的declare声明语句)。
- SIGNAL语句中的SQLSTATE值不应以'00'开头,包括SQLSTATE直接定义的也包括condition_name隐式表示的。
- signal_information_item:每个condition_information_item_name只能在SET子句中指定一次,否则会出现重复条件信息项的错误。有效的simple_value_specification可以使用存储过程或函数的参数,declare声明的局部变量,用户自定义变量,系统变量或可转为对应数据类型的函数等。
- SQLSTATE错误类别解析参见表1。
- condition_information_item_name参数参见表2。
表 1 SQLSTATE错误类别
类型 | MESSAGE_TEXT | MYSQL_ERRNO | |
---|---|---|---|
class = '00' | success | ||
class = '01' | warning | 'Unhandled user-defined warning condition' | 01000 |
class = '02' | not found | 'Unhandled user-defined not found condition' | 02000 |
class > '02' | exception | 'Unhandled user-defined exception condition' | 03000 |
表 2 condition_information_item_name参数列表
参数 | 解析 |
---|---|
CLASS_ORIGIN | 字符串,包含RETURNED_SQLSTATE值的类别的字符串,默认为空。 |
SUBCLASS_ORIGIN | 字符串,包含RETURNED_SQLSTATE值的子类的字符串,默认为空。 |
MESSAGE_TEXT | 字符串,条件的错误消息。 |
MYSQL_ERRNO | 字符串,条件的MySQL错误代码。 |
CONSTRAINT_CATALOG | 字符串,违反约束的catalog,默认为空。 |
CONSTRAINT_SCHEMA | 字符串,违反约束的schema,默认为空。 |
CONSTRAINT_NAME | 字符串,违反约束的name,默认为空。 |
CATALOG_NAME | 字符串,与条件相关的catalog,默认为空。 |
SCHEMA_NAME | 字符串,与条件相关的schema,默认为空。 |
TABLE_NAME | 字符串,与条件相关的table,默认为空。 |
COLUMN_NAME | 字符串,与条件相关的column,默认为空。 |
CURSOR_NAME | 字符串,cursor的名称,默认为空。 |
RESIGNAL语句
resignal语句和signal语句一样,也可以抛出错误,但resignal可以在抛出错误条件信息之前更改某些或全部信息。语法如下:
RESIGNAL [condition_value]
[SET signal_information_item
[, signal_information_item] ...]
虽然,signal和resignal都可以抛出错误,但两者仍存在一些不同:
- resignal必须在错误或警告处理程序中使用,否则会收到一条错误消息:RESIGNAL when handler is not active。但是signal语句可以在存储过程的任何位置中使用。
- 在resignal语法中可以省略resiganl语句的所有属性,甚至可以省略SQLSTATE的值。但是signal语句必须要有SQLSTATE值。
场景说明:
- 只有RESIGNAL,即RESIGNAL。这种形式的RESIGNAL语句直接恢复上一个诊断区域的堆栈,并将其设置为当前诊断区域,相当于未修改错误信息,直接抛出。
- 带有signal_information_item的RESIGNAL,即RESIGNAL SET signal_information_item [, signal_information_item] …。与仅有RESIGNAL的场景一致,但该场景会根据signal_information_item修改弹出的错误信息。
- 带有condition_value和signal_information_item的RESIGNAL,即RESIGNAL condition_value [SET signal_information_item [, signal_information_item] …]。该场景会根据condition_value和signal_information_item更改错误信息,并将修改后的错误信息添加到诊断区域中。
约束说明:
- signal/resignal语法只在B模式下生效,即sql_compatibility = 'B'。
- resignal只能在declare … handler语句中调用。
- signal/resignal语句中,给condition_information_item_name赋值为NULL时,执行会报错。
- opengauss中的warning不会触发declare handler异常处理机制,但signal和resignal触发的warning告警会触发declare handler异常处理机制。
示例 :
-- 在非declare ... handler语句中调用signal的场景
CREATE OR REPLACE PROCEDURE p() IS
BEGIN
SIGNAL SQLSTATE '22012' SET MESSAGE_TEXT = 'this is error';
END;
/
call p();
ERROR: this is error
CONTEXT: PL/pgSQL function p() line 2 at SIGNAL
show warnings;
level | code | message
-------+-------+---------------
Error | 03000 | this is error
(1 row)
-- 在declare ... handler语句中调用signal的场景
DROP TABLE IF EXISTS t1;
CREATE OR REPLACE PROCEDURE p() IS
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE '42P01'
BEGIN
SIGNAL SQLSTATE '22012' SET MESSAGE_TEXT = 'this is error', MYSQL_ERRNO = 100;
END;
DROP TABLE t1;
END;
/
call p();
ERROR: this is error
CONTEXT: PL/pgSQL function p() line 4 at SIGNAL
show warnings;
level | code | message
-------+------+---------------
Error | 100 | this is error
(1 row)
-- 只有RESIGNAL的场景
DROP TABLE IF EXISTS t1;
CREATE OR REPLACE PROCEDURE p() IS
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE '42P01'
BEGIN
RESIGNAL;
END;
DROP TABLE t1;
END;
/
call p();
ERROR: table "t1" does not exist
CONTEXT: PL/pgSQL function p() line 4 at RESIGNAL
show warnings;
level | code | message
-------+-------+---------------------------
Error | 42P01 | table "t1" does not exist
(1 row)
-- RESIGNAL SET signal_information_item的场景
DROP TABLE IF EXISTS t1;
CREATE OR REPLACE PROCEDURE p() IS
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE '42P01'
BEGIN
RESIGNAL SET MESSAGE_TEXT = 'this is error', MYSQL_ERRNO = 100;
END;
DROP TABLE t1;
END;
/
call p();
ERROR: this is error
CONTEXT: PL/pgSQL function p() line 4 at RESIGNAL
show warnings;
level | code | message
-------+------+---------------
Error | 100 | this is error
(1 row)
-- RESIGNAL condition_value SET signal_information_item
DROP TABLE IF EXISTS t1;
CREATE OR REPLACE PROCEDURE p() IS
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE '42P01'
BEGIN
RESIGNAL SQLSTATE '22012' SET MESSAGE_TEXT = 'this is error', MYSQL_ERRNO = 100;
END;
DROP TABLE t1;
END;
/
call p();
ERROR: this is error
CONTEXT: PL/pgSQL function p() line 4 at RESIGNAL
show warnings;
level | code | message
-------+-------+---------------------------
Error | 42P01 | table "t1" does not exist
Error | 100 | this is error
(2 rows)
意见反馈