文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  SIGNAL 语句

15.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 语句(请参阅 第 15.6.7.3 节“GET DIAGNOSTICS 语句”)。有关诊断区域的信息,请参阅 第 15.6.7.7 节“MySQL 诊断区域”

SIGNAL 概述

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_nameSET 子句中只能指定一次。否则,会发生 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 的表,因此错误处理程序被激活。错误处理程序销毁原始错误(no such table)并创建一个新的错误,其 SQLSTATE'99999',消息为 An error occurred

信号条件信息项

下表列出了可以在 SIGNAL(或 RESIGNAL)语句中设置的诊断区域条件信息项的名称。除 MYSQL_ERRNO(它是 MySQL 扩展)外,所有项目均为标准 SQL。有关这些项目的更多信息,请参阅 第 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'(成功)

    非法。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 执行后可访问的错误值是由 SIGNAL 语句引发的 SQLSTATE 值以及 MESSAGE_TEXTMYSQL_ERRNO 项。这些值可从 C API 获得

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

要从诊断区域检索信息,请使用 GET DIAGNOSTICS 语句(请参阅 第 15.6.7.3 节“GET DIAGNOSTICS 语句”)。有关诊断区域的信息,请参阅 第 15.6.7.7 节“MySQL 诊断区域”

信号对处理程序、游标和语句的影响

信号对语句执行的影响因信号类别而异。类别决定了错误的严重程度。MySQL 忽略 sql_mode 系统变量的值;特别是,严格 SQL 模式无关紧要。MySQL 还会忽略 IGNORESIGNAL 的目的是显式引发用户生成的错误,因此永远不会忽略信号。

在以下描述中,“未处理” 表示尚未使用 DECLARE ... HANDLER 为指示的 SQLSTATE 值定义处理程序。

  • 类别 = '00'(成功)

    非法。SQLSTATE 值以 '00' 开头表示成功,对于 SIGNAL 无效。

  • 类别 = '01'(警告)

    warning_count 系统变量的值会增加。SHOW WARNINGS 显示信号。SQLWARNING 处理程序捕获信号。

    无法从存储函数返回警告,因为导致函数返回的 RETURN 语句会清除诊断区域。因此,该语句会清除诊断区域中可能存在的任何警告(并将 warning_count 重置为 0)。

  • 类别 = '02'(未找到)

    NOT FOUND 处理程序捕获信号。对游标没有影响。如果在存储函数中未处理信号,则语句结束。

  • 类别 > '02'(异常)

    SQLEXCEPTION 处理程序捕获信号。如果在存储函数中未处理信号,则语句结束。

  • 类别 = '40'

    被视为普通异常。