抛出错误语句

介绍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语句获取。

参数说明

  1. condition_value表示要返回的错误值,该值可以是SQLSTATE值,也可以是condition_name(declare … condition语法声明的declare声明语句)。
  2. SIGNAL语句中的SQLSTATE值不应以'00'开头,包括SQLSTATE直接定义的也包括condition_name隐式表示的。
  3. signal_information_item:每个condition_information_item_name只能在SET子句中指定一次,否则会出现重复条件信息项的错误。有效的simple_value_specification可以使用存储过程或函数的参数,declare声明的局部变量,用户自定义变量,系统变量或可转为对应数据类型的函数等。
  4. SQLSTATE错误类别解析参见表1。
  5. condition_information_item_name参数参见表2。

表 1 SQLSTATE错误类别

类型MESSAGE_TEXTMYSQL_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值。

场景说明:

  1. 只有RESIGNAL,即RESIGNAL。这种形式的RESIGNAL语句直接恢复上一个诊断区域的堆栈,并将其设置为当前诊断区域,相当于未修改错误信息,直接抛出。
  2. 带有signal_information_item的RESIGNAL,即RESIGNAL SET signal_information_item [, signal_information_item] …。与仅有RESIGNAL的场景一致,但该场景会根据signal_information_item修改弹出的错误信息。
  3. 带有condition_value和signal_information_item的RESIGNAL,即RESIGNAL condition_value [SET signal_information_item [, signal_information_item] …]。该场景会根据condition_value和signal_information_item更改错误信息,并将修改后的错误信息添加到诊断区域中。

约束说明:

  1. signal/resignal语法只在B模式下生效,即sql_compatibility = 'B'。
  2. resignal只能在declare … handler语句中调用。
  3. signal/resignal语句中,给condition_information_item_name赋值为NULL时,执行会报错。
  4. 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)
意见反馈
编组 3备份
    openGauss 2024-04-27 00:42:13
    取消