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
语句(请参阅
第 13.6.7.3 节,“GET DIAGNOSTICS 语句”)。有关诊断区域的信息,请参阅第 13.6.7.7 节,“MySQL 诊断区域”。
condition_value
语句中的
表示SIGNAL
要返回的错误值。它可以是一个
SQLSTATE
值(一个 5 个字符的字符串文字)或一个condition_name
引用先前定义的命名条件的
值DECLARE ...
CONDITION
(请参阅第 13.6.7.1 节,“DECLARE ... CONDITION 语句”)。
值可以SQLSTATE
指示错误、警告或“未找到。”值的前两个字符表示其错误类别,如信号条件信息项中所述。某些信号值会导致语句终止;请参阅
信号对处理程序、游标和语句的影响。
语句的SQLSTATE
值
SIGNAL
不应以 开头,'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
会发生错误。
可以使用存储过程或函数参数、用 声明的存储程序局部变量、用户定义的变量、系统变量或文字simple_value_specification
来指定
有效的指示符。DECLARE
字符字面量可以包括_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()
发出警告信号,因为SQLSTATE
以 开头的值是'01'
警告类中的信号。警告不会终止程序,并且可以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'
.
有关在条件发生时服务器如何选择处理程序的信息,请参阅第 13.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
)语句中设置的诊断区域条件信息项的名称。所有项目都是标准 SQL,除了MYSQL_ERRNO
,它是 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。
在语句
中分配NULL
给条件信息项是非法的。SIGNAL
SIGNAL
语句总是SQLSTATE
直接或间接地通过引用用值定义的命名条件来指定
值SQLSTATE
。一个值的前两个字符SQLSTATE
是它的类别,类别决定了条件信息项的默认值:
类 =
'00'
(成功)非法的。
SQLSTATE
开头的值'00'
表示成功并且对 无效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
执行
后可访问的错误值是
语句
和
项目SQLSTATE
引发
的值。这些值可从 C API 获得:
SIGNAL
MESSAGE_TEXT
MYSQL_ERRNO
mysql_sqlstate()
返回SQLSTATE
值。mysql_errno()
返回MYSQL_ERRNO
值。mysql_error()
返回MESSAGE_TEXT
值。
在 SQL 级别,and 的输出SHOW
WARNINGS
表示SHOW
ERRORS
and列
中
的MYSQL_ERRNO
andMESSAGE_TEXT
值
。Code
Message
要从诊断区域检索信息,请使用
GET DIAGNOSTICS
语句(请参阅
第 13.6.7.3 节,“GET DIAGNOSTICS 语句”)。有关诊断区域的信息,请参阅第 13.6.7.7 节,“MySQL 诊断区域”。
根据信号类别,信号对语句执行有不同的影响。该类确定错误的严重程度。MySQL忽略
sql_mode
系统变量的值;特别是,严格的 SQL 模式无关紧要。MySQL 也忽略IGNORE
: 的目的
SIGNAL
是显式地引发用户生成的错误,因此永远不会忽略信号。
在下面的描述中,“ unhandled ”意味着没有为信号SQLSTATE
值定义
处理程序DECLARE ...
HANDLER
。
类 =
'00'
(成功)非法的。
SQLSTATE
开头的值'00'
表示成功并且对 无效SIGNAL
。类 =
'01'
(警告)系统变量的值
warning_count
上升。SHOW WARNINGS
显示信号。SQLWARNING
处理程序捕获信号。存储函数无法返回警告,因为
RETURN
导致函数返回的语句清除了诊断区域。因此,该语句清除了那里可能存在的任何警告(并重置warning_count
为 0)。类 =
'02'
(未找到)NOT FOUND
处理程序捕获信号。对游标没有影响。如果信号在存储函数中未处理,则语句结束。类>
'02'
(例外)SQLEXCEPTION
处理程序捕获信号。如果信号在存储函数中未处理,则语句结束。类 =
'40'
视为普通异常。