13.6.7.5 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
}
condition_name, simple_value_specification:
(see following discussion)
SIGNAL是“返回”错误的方法。 SIGNAL将错误信息提供给处理程序,应用程序外部或 Client 端。此外,它还提供对错误 Feature(错误编号,SQLSTATE
值,消息)的控制。如果没有SIGNAL,则必须求助于变通办法,例如故意引用不存在的 table 以使例程返回错误。
执行SIGNAL语句不需要特权。
要从诊断区域检索信息,请使用GET DIAGNOSTICS语句(请参阅第 13.6.7.3 节“获取诊断声明”)。有关诊断区域的信息,请参见第 13.6.7.7 节“ MySQL 诊断区域”。
SIGNAL Overview
SIGNAL语句中的* condition_value
table 示要返回的错误值。它可以是SQLSTATE
值(5 个字符的字符串 Literals)或 condition_name
*,它 table 示先前用声明...条件定义的命名条件(请参见第 13.6.7.1 节“ DECLARE ... CONDITION 语句”)。
SQLSTATE
值可以指示错误,警告或“未找到”。值的前两个字符 table 示其错误类别,如signal 状态信息项中所述。一些 signal 值会导致语句终止。参见signal 对处理程序,游标和语句的影响。
SIGNAL语句的SQLSTATE
值不应以'00'
开头,因为这样的值 table 示成功,并且对于发 signal 错误无效。无论是直接在SIGNAL语句中指定还是在语句中引用的命名条件中指定SQLSTATE
值,都是如此。如果该值无效,则会发生Bad SQLSTATE
错误。
要发出通用的SQLSTATE
值,请使用'45000'
,这 table 示“未处理的用户定义的异常”。
SIGNAL语句可选地包含SET
子句,该子句在* condition_information_item_name
* = * simple_value_specification
*分配列 table 中包含多个 signal 项,并用逗号分隔。
每个condition_information_item_name
*只能在SET
子句中指定一次。否则,发生Duplicate condition information item
错误。
可以使用存储过程或函数参数,用DECLARE声明的存储程序局部变量,用户定义的变量,系统变量或 Literals 来指定有效* simple_value_specification
指示符。字符 Literals 可能包含 _charset
*引荐。
有关允许的condition_information_item_name
*值的信息,请参见signal 状态信息项。
以下过程根据 Importing 参数pval
的值来发出错误或警告 signal:
CREATE PROCEDURE p (pval INT)
BEGIN
DECLARE specialty CONDITION FOR SQLSTATE '45000';
IF pval = 0 THEN
SIGNAL SQLSTATE '01000';
ELSEIF pval = 1 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'An error occurred';
ELSEIF pval = 2 THEN
SIGNAL specialty
SET MESSAGE_TEXT = 'An error occurred';
ELSE
SIGNAL SQLSTATE '01000'
SET MESSAGE_TEXT = 'A warning occurred', MYSQL_ERRNO = 1000;
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'An error occurred', MYSQL_ERRNO = 1001;
END IF;
END;
如果pval
为 0,则p()
发出警告,因为以'01'
开头的SQLSTATE
值是警告类中的 signal。该警告不会终止该过程,并且在该过程返回后可以使用SHOW WARNINGS进行查看。
如果pval
为 1,则p()
发出错误 signal 并设置MESSAGE_TEXT
条件信息项。错误将终止该过程,并返回包含错误信息的文本。
如果pval
为 2,则发出相同的错误 signal,尽管在这种情况下使用命名条件指定了SQLSTATE
值。
如果pval
是其他值,则p()
首先发出警告并设置消息文本和错误编号条件信息项。该警告不会终止该过程,因此 continue 执行,然后p()
table 示错误。该错误确实终止了该过程。警告设置的消息文本和错误编号将替换为错误设置的值,并随错误信息一起返回。
SIGNAL通常用于存储程序中,但是它是 MySQL 扩展,可以在处理程序上下文之外使用。例如,如果您调用mysqlClient 端程序,则可以在提示符下 Importing 以下任何语句:
SIGNAL SQLSTATE '77777';
CREATE TRIGGER t_bi BEFORE INSERT ON t
FOR EACH ROW SIGNAL SQLSTATE '77777';
CREATE EVENT e ON SCHEDULE EVERY 1 SECOND
DO SIGNAL SQLSTATE '77777';
SIGNAL根据以下规则执行:
如果SIGNAL语句指示特定的SQLSTATE
值,则该值用于 table 示指定的条件。例:
CREATE PROCEDURE p (divisor INT)
BEGIN
IF divisor = 0 THEN
SIGNAL SQLSTATE '22012';
END IF;
END;
如果SIGNAL语句使用命名条件,则必须在适用于SIGNAL语句的某个范围内声明该条件,并且必须使用SQLSTATE
值(而不是 MySQL 错误号)进行定义。例:
CREATE PROCEDURE p (divisor INT)
BEGIN
DECLARE divide_by_zero CONDITION FOR SQLSTATE '22012';
IF divisor = 0 THEN
SIGNAL divide_by_zero;
END IF;
END;
如果命名条件在SIGNAL语句的范围内不存在,则会发生Undefined CONDITION
错误。
如果SIGNAL引用使用 MySQL 错误号而不是SQLSTATE
值定义的命名条件,则会发生SIGNAL/RESIGNAL can only use a CONDITION defined with SQLSTATE
错误。以下语句导致该错误,因为命名条件与 MySQL 错误号相关联:
DECLARE no_such_table CONDITION FOR 1051;
SIGNAL no_such_table;
如果在不同的作用域中多次声明了具有给定名称的条件,则应用具有最局部作用域的声明。请考虑以下过程:
CREATE PROCEDURE p (divisor INT)
BEGIN
DECLARE my_error CONDITION FOR SQLSTATE '45000';
IF divisor = 0 THEN
BEGIN
DECLARE my_error CONDITION FOR SQLSTATE '22012';
SIGNAL my_error;
END;
END IF;
SIGNAL my_error;
END;
如果divisor
为 0,则执行第一个SIGNAL语句。最里面的my_error
条件声明适用,提高SQLSTATE
'22012'
。
如果divisor
不为 0,则执行第二个SIGNAL语句。最外面的my_error
条件声明适用,提高SQLSTATE
'45000'
。
有关在条件发生时服务器如何选择处理程序的信息,请参见第 13.6.7.6 节“处理程序的范围规则”。
可以在异常处理程序中引发 signal:
CREATE PROCEDURE p ()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SIGNAL SQLSTATE VALUE '99999'
SET MESSAGE_TEXT = 'An error occurred';
END;
DROP TABLE no_such_table;
END;
CALL p()
到达DROP TABLE语句。没有名为no_such_table
的 table,因此错误处理程序已激活。错误处理程序销毁原始错误(“没有这样的 table”),并使用SQLSTATE
'99999'
和消息An error occurred
产生新的错误。
signal 状况信息项
下 table 列出了可以在SIGNAL(或RESIGNAL)语句中设置的诊断区域条件信息项的名称。除MYSQL_ERRNO
外,所有项均为标准 SQL,这是 MySQL 扩展。有关这些项目的更多信息,请参见第 13.6.7.7 节“ MySQL 诊断区域”。
Item Name Definition
--------- ----------
CLASS_ORIGIN VARCHAR(64)
SUBCLASS_ORIGIN VARCHAR(64)
CONSTRAINT_CATALOG VARCHAR(64)
CONSTRAINT_SCHEMA VARCHAR(64)
CONSTRAINT_NAME VARCHAR(64)
CATALOG_NAME VARCHAR(64)
SCHEMA_NAME VARCHAR(64)
TABLE_NAME VARCHAR(64)
COLUMN_NAME VARCHAR(64)
CURSOR_NAME VARCHAR(64)
MESSAGE_TEXT VARCHAR(128)
MYSQL_ERRNO SMALLINT UNSIGNED
字符项的字符集为 UTF-8.
在SIGNAL语句中将NULL
分配给条件信息项是非法的。
SIGNAL语句始终直接或间接地通过引用用SQLSTATE
值定义的命名条件来指定SQLSTATE
值。 SQLSTATE
值的前两个字符是其类,该类确定条件信息项的默认值:
- 类别=
'00'
(成功)
非法。以'00'
开头的SQLSTATE
值 table 示成功,但对于SIGNAL无效。
- 类别=
'01'
(警告)
MESSAGE_TEXT = 'Unhandled user-defined warning condition';
MYSQL_ERRNO = ER_SIGNAL_WARN
- 类别=
'02'
(未找到)
MESSAGE_TEXT = 'Unhandled user-defined not found condition';
MYSQL_ERRNO = ER_SIGNAL_NOT_FOUND
- 类>
'02'
(exception)
MESSAGE_TEXT = 'Unhandled user-defined exception condition';
MYSQL_ERRNO = ER_SIGNAL_EXCEPTION
对于合法类,其他条件信息项设置如下:
CLASS_ORIGIN = SUBCLASS_ORIGIN = '';
CONSTRAINT_CATALOG = CONSTRAINT_SCHEMA = CONSTRAINT_NAME = '';
CATALOG_NAME = SCHEMA_NAME = TABLE_NAME = COLUMN_NAME = '';
CURSOR_NAME = '';
SIGNAL执行后可访问的错误值是SIGNAL语句以及MESSAGE_TEXT
和MYSQL_ERRNO
项引发的SQLSTATE
值。这些值可从 C API 获得:
-
mysql_sqlstate()返回
SQLSTATE
的值。 -
mysql_errno()返回
MYSQL_ERRNO
的值。 -
mysql_error()返回
MESSAGE_TEXT
的值。
在 SQL 级别上,SHOW WARNINGS和SHOW ERRORS的输出指示Code
和Message
列中的MYSQL_ERRNO
和MESSAGE_TEXT
值。
要从诊断区域检索信息,请使用GET DIAGNOSTICS语句(请参阅第 13.6.7.3 节“获取诊断声明”)。有关诊断区域的信息,请参见第 13.6.7.7 节“ MySQL 诊断区域”。
signal 对处理程序,游标和语句的影响
signal 对 signal 执行的影响取决于 signal 类。该类确定错误的严重程度。 MySQL 会忽略sql_mode系统变量的值;特别是,严格的 SQL 模式无关紧要。 MySQL 还忽略IGNORE
:SIGNAL的目的是显式引发用户生成的错误,因此永远不会忽略 signal。
在以下描述中,“未处理”table 示尚未使用声明...处理程序定义 signalSQLSTATE
值的处理程序。
- 类别=
'00'
(成功)
非法。以'00'
开头的SQLSTATE
值 table 示成功,但对于SIGNAL无效。
- 类别=
'01'
(警告)
warning_count系统变量的值上升。 SHOW WARNINGS显示 signal。 SQLWARNING
处理程序捕获 signal。
无法从存储的函数返回警告,因为导致函数返回的RETURN语句清除了诊断区域。因此,该语句清除了那里可能存在的所有警告(并将warning_count重置为 0)。
- 类别=
'02'
(未找到)
NOT FOUND
处理程序捕获 signal。对光标没有影响。如果在存储的函数中未处理该 signal,则语句结束。
- 类>
'02'
(exception)
SQLEXCEPTION
处理程序捕获 signal。如果在存储的函数中未处理该 signal,则语句结束。
- 类别=
'40'
被视为普通异常。