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_TEXTMYSQL_ERRNO项引发的SQLSTATE值。这些值可从 C API 获得:

在 SQL 级别上,SHOW WARNINGSSHOW ERRORS的输出指示CodeMessage列中的MYSQL_ERRNOMESSAGE_TEXT值。

要从诊断区域检索信息,请使用GET DIAGNOSTICS语句(请参阅第 13.6.7.3 节“获取诊断声明”)。有关诊断区域的信息,请参见第 13.6.7.7 节“ MySQL 诊断区域”

signal 对处理程序,游标和语句的影响

signal 对 signal 执行的影响取决于 signal 类。该类确定错误的严重程度。 MySQL 会忽略sql_mode系统变量的值;特别是,严格的 SQL 模式无关紧要。 MySQL 还忽略IGNORESIGNAL的目的是显式引发用户生成的错误,因此永远不会忽略 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'

被视为普通异常。