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: (seefollowing discussion)
SIGNAL
是“返回”错误的方法。SIGNAL
将错误信息提供给处理程序,应用程序的外部或客户端。同样,它提供对错误特征(错误编号,SQLSTATE
值,消息)的控制。如果不使用SIGNAL
,则必须求助于变通办法,例如故意引用不存在的表以导致例程返回错误。
执行该SIGNAL
语句不需要特权。
要从诊断区域检索信息,请使用该GET DIAGNOSTICS
语句(请参见“ GET DIAGNOSTICS语句”)。有关诊断区域的信息,请参见“ MySQL诊断区域”。
- 信号概述
- 信号状态信息项
- 信号对处理程序,游标和语句的影响
信号概述
在condition_value
一个SIGNAL
声明中表示要返回错误值。它可以是一个SQLSTATE
值(5个字符的字符串文字)或一个condition_name
引用先前定义的命名条件的值DECLARE ... CONDITION
(请参见“ 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 specialtyCONDITION FOR SQLSTATE '45000';IF pval = 0THEN SIGNAL SQLSTATE '01000';ELSEIF pval = 1THEN SIGNAL SQLSTATE '45000'SET MESSAGE_TEXT = 'An error occurred';ELSEIF pval = 2THEN SIGNAL specialtySET 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_biBEFORE INSERT ON tFOR EACH ROW SIGNAL SQLSTATE '77777';CREATE EVENT eON SCHEDULE EVERY 1SECOND DO SIGNAL SQLSTATE '77777';
SIGNAL
根据以下规则执行:
如果SIGNAL
语句指示特定SQLSTATE
值,则该值用于表示指定的条件。例:
CREATE PROCEDURE p (divisor INT)BEGIN IF divisor = 0THEN SIGNAL SQLSTATE '22012';END IF ;END ;
如果该SIGNAL
语句使用命名条件,则必须在适用于该SIGNAL
语句的某个范围内声明该条件,并且必须使用SQLSTATE
值(而不是MySQL错误号)进行定义。例:
CREATE PROCEDURE p (divisor INT)BEGIN DECLARE divide_by_zeroCONDITION FOR SQLSTATE '22012';IF divisor = 0THEN 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_tableCONDITION FOR 1051;SIGNAL no_such_table;
如果在不同的作用域中多次声明了具有给定名称的条件,则使用具有最局部作用域的声明。请考虑以下过程:
CREATE PROCEDURE p (divisor INT)BEGIN DECLARE my_errorCONDITION FOR SQLSTATE '45000';IF divisor = 0THEN BEGIN DECLARE my_errorCONDITION FOR SQLSTATE '22012';SIGNAL my_error;END ;END IF ;SIGNAL my_error;END ;
如果divisor
为0,则SIGNAL
执行第一条语句。最里面的my_error
条件声明适用,raising SQLSTATE
'22012'
。
如果divisor
不为0,则SIGNAL
执行第二条语句。最外面的my_error
条件声明适用,raising SQLSTATE
'45000'
。
有关在条件发生时服务器如何选择处理程序的信息,请参见“处理程序的作用域规则”。
可以在异常处理程序中引发信号:
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扩展。有关这些项目的更多信息,请参见“ 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级别,SHOW WARNINGS
and 的输出SHOW ERRORS
表示and 列中的MYSQL_ERRNO
and MESSAGE_TEXT
值。Code
Message
要从诊断区域检索信息,请使用该GET DIAGNOSTICS
语句(请参见“ GET DIAGNOSTICS语句”)。有关诊断区域的信息,请参见“ MySQL诊断区域”。
信号对处理程序,游标和语句的影响
根据信号类别,信号对语句执行的影响不同。该类确定错误的严重程度。MySQL会忽略sql_mode
系统变量的值。特别是,严格的SQL模式无关紧要。MySQL还忽略了IGNORE
:的目的SIGNAL
是显式引发用户生成的错误,因此永远不会忽略信号。
在以下描述中,“未处理”表示SQLSTATE
尚未使用定义信号值的处理程序DECLARE ... HANDLER
。
类别=
'00'
(成功)非法。
SQLSTATE
以开头的值'00'
表示成功,不适用于SIGNAL
。类别=
'01'
(警告)warning_count
系统变量的值上升。SHOW WARNINGS
显示信号。SQLWARNING
处理程序捕获信号。无法从存储的函数返回警告,因为
RETURN
引起函数返回的语句清除了诊断区域。因此,该语句清除了那里可能存在的所有警告(并将其重置warning_count
为0)。类=
'02'
(未找到)NOT FOUND
处理程序捕获信号。对光标没有影响。如果未在存储的函数中处理信号,则语句结束。类别>
'02'
(例外)SQLEXCEPTION
处理程序捕获信号。如果未在存储的函数中处理信号,则语句结束。类=
'40'
被视为普通异常。