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 向处理程序、应用程序的外层部分或客户端提供错误信息。此外,它还提供对错误特征(错误号、SQLSTATE 值、消息)的控制。如果没有 SIGNAL,则需要采用解决方法,例如故意引用不存在的表以使例程返回错误。
执行 SIGNAL 语句不需要任何权限。
要从诊断区域检索信息,请使用 GET DIAGNOSTICS 语句(参见 第 15.6.7.3 节,“GET DIAGNOSTICS 语句”)。有关诊断区域的信息,请参见 第 15.6.7.7 节,“MySQL 诊断区域”。
在 SIGNAL 语句中,condition_value 指示要返回的错误值。它可以是 SQLSTATE 值(一个 5 个字符的字符串字面量),也可以是 condition_name,该名称引用先前使用 DECLARE ... CONDITION 定义的命名条件(参见 第 15.6.7.1 节,“DECLARE ... CONDITION 语句”)。
SQLSTATE 值可以指示错误、警告或 “未找到。” 值的前两个字符指示其错误类别,如 信号条件信息项 中所述。某些信号值会导致语句终止;参见 信号对处理程序、游标和语句的影响。
SIGNAL 语句的 SQLSTATE 值不应以 '00' 开头,因为此类值表示成功,不适用于信号错误。无论 SQLSTATE 值是在 SIGNAL 语句中直接指定,还是在语句中引用的命名条件中指定,都是如此。如果值无效,则会发生 Bad SQLSTATE 错误。
要发出通用 SQLSTATE 值,请使用 '45000',这意味着 “未处理的用户定义异常。”
SIGNAL 语句可以选择包含一个 SET 子句,该子句包含多个信号项,这些项在一个 condition_information_item_name = simple_value_specification 赋值列表中,用逗号分隔。
每个 condition_information_item_name 只能在 SET 子句中指定一次。否则,会发生 Duplicate condition information item 错误。
可以使用存储过程或函数参数、使用 DECLARE 声明的存储程序局部变量、用户定义变量、系统变量或字面量来指定有效的 simple_value_specification 指示符。字符字面量可以包含 _charset 引入器。
有关允许的 condition_information_item_name 值的信息,请参见 信号条件信息项。
以下过程根据输入参数 pval 的值发出错误或警告
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 值是警告类别中的信号。警告不会终止过程,并且可以使用 SHOW WARNINGS 在过程返回后查看。
如果 pval 为 1,则 p() 会发出错误并设置 MESSAGE_TEXT 条件信息项。错误会终止过程,并且文本会与错误信息一起返回。
如果 pval 为 2,则会发出相同的错误,尽管在这种情况下,SQLSTATE 值是使用命名条件指定的。
如果 pval 为任何其他值,则 p() 首先会发出警告并设置消息文本和错误号条件信息项。此警告不会终止过程,因此执行将继续,然后 p() 会发出错误。错误会终止过程。由警告设置的消息文本和错误号将被错误设置的值替换,这些值将与错误信息一起返回。
SIGNAL 通常用于存储程序中,但它是 MySQL 的扩展,允许在处理程序上下文之外使用它。例如,如果调用 mysql 客户端程序,则可以在提示符处输入以下任何语句
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 值,则该值用于发出指定的条件。示例
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'。
有关服务器在发生条件时如何选择处理程序的信息,请参见 第 15.6.7.6 节,“处理程序的范围规则”。
可以在异常处理程序中引发信号
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 的表,因此错误处理程序被激活。错误处理程序销毁原始错误(“不存在该表”),并使用 SQLSTATE '99999' 和消息 An error occurred 创建一个新的错误。
下表列出了可以在 SIGNAL(或 RESIGNAL)语句中设置的诊断区域条件信息项的名称。除了 MYSQL_ERRNO 之外,所有项目都是标准 SQL,它是 MySQL 扩展。有关这些项目的更多信息,请参见 第 15.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值表示成功,不适用于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'(异常)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 语句引发的 SQLSTATE 值以及 MESSAGE_TEXT 和 MYSQL_ERRNO 项。这些值可从 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 语句(参见 第 15.6.7.3 节,“GET DIAGNOSTICS 语句”)。有关诊断区域的信息,请参见 第 15.6.7.7 节,“MySQL 诊断区域”。
信号对语句执行的影响取决于信号类别。类别决定错误的严重程度。MySQL 会忽略 sql_mode 系统变量的值;特别是严格 SQL 模式无关紧要。MySQL 也会忽略 IGNORE:SIGNAL 的目的是显式地引发用户生成的错误,因此信号永远不会被忽略。
在以下描述中,“未处理”是指没有使用 DECLARE ... HANDLER 为发出的 SQLSTATE 值定义处理程序。
类别 =
'00'(成功)非法。以
'00'开头的SQLSTATE值表示成功,不适用于SIGNAL。类别 =
'01'(警告)warning_count系统变量的值会增加。SHOW WARNINGS会显示信号。SQLWARNING处理程序会捕获信号。存储函数无法返回警告,因为会导致函数返回的
RETURN语句会清除诊断区域。因此,该语句会清除可能存在的任何警告(并将warning_count重置为 0)。类别 =
'02'(未找到)NOT FOUND处理程序会捕获信号。对游标没有影响。如果信号在存储函数中未处理,则语句会结束。类别 >
'02'(异常)SQLEXCEPTION处理程序会捕获信号。如果信号在存储函数中未处理,则语句会结束。类别 =
'40'被视为普通异常。