Documentation Home

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向处理程序、应用程序的外部部分或客户端提供错误信息。此外,它还提供对错误特征(错误号、错误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指示错误、警告或未找到。值的前两个字符表示其错误类别,如信号条件信息项中所述。某些信号值会导致语句终止;请参阅 信号对处理程序、游标和语句的影响

语句的SQLSTATESIGNAL不应以 开头,'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 获得: SIGNALMESSAGE_TEXTMYSQL_ERRNO

在 SQL 级别,and 的输出SHOW WARNINGS表示SHOW ERRORSand列 中 的MYSQL_ERRNO andMESSAGE_TEXT值 。CodeMessage

要从诊断区域检索信息,请使用 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'

    视为普通异常。