Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

15.6.7.5 信号语句

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)

信号 是返回错误的一种方式。信号 提供错误信息给处理程序、应用程序的外部部分或客户端。此外,它还提供了对错误特征(错误号、SQLSTATE 值、消息)的控制。如果没有 信号,则需要使用诸如故意引用不存在的表来引发错误的 workaround。

执行 信号 语句不需要任何权限。

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

信号概述

信号 语句中,condition_value 指示要返回的错误值。它可以是一个 SQLSTATE 值(一个 5 个字符的字符串文字)或一个 condition_name,它引用了之前使用 DECLARE ... CONDITION 定义的命名条件(见 第 15.6.7.1 节,“DECLARE ... CONDITION 语句”)。

一个 SQLSTATE 值可以指示错误、警告或 未找到。 第一个两个字符指示错误类别,如 信号条件信息项 中所讨论的那样。一些信号值会导致语句终止;见 信号对处理程序、游标和语句的影响

信号 语句中,SQLSTATE 值不应该以 '00' 开头,因为这些值表示成功并且不适合信号错误。如果值无效,将发生 Bad SQLSTATE 错误。

要信号一个通用的 SQLSTATE 值,请使用 '45000',它表示 未处理的用户定义异常。

可选地,信号 语句包括一个 SET 子句,该子句包含多个信号项,以逗号分隔的 condition_information_item_name = simple_value_specification 赋值语句。

每个 condition_information_item_name 只能在 SET 子句中指定一次。否则,将发生 Duplicate condition information item 错误。

有效的 simple_value_specification 可以使用存储过程或函数参数、存储程序局部变量、用户定义变量、系统变量或文字指定。字符文字可以包括一个 _charset introducer。

关于允许的 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'

关于服务器如何在条件发生时选择处理器,请参阅 第 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) 语句中设置的诊断区域条件信息项。所有项都是标准 SQL,除了 MYSQL_ERRNO,它是一个 MySQL 扩展。有关这些项的更多信息,请参阅 第 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 值的命名条件定义。

  • 类 = '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 的输出表明了 MYSQL_ERRNOMESSAGE_TEXT 值在 CodeMessage 列中。

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

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

信号对语句执行的影响取决于信号类。类确定错误的严重程度。MySQL 忽视 sql_mode 系统变量的值;特别是,严格 SQL 模式不重要。MySQL 也忽视 IGNORESIGNAL 的意图是明确地引发用户生成的错误,因此信号永远不会被忽视。

在以下描述中,未处理 表示没有为信号的 SQLSTATE 值定义处理程序使用 DECLARE ... HANDLER

  • 类 = '00' (成功)

    非法。 SQLSTATE 值以 '00' 开头,表示成功,不适用于 SIGNAL

  • 类 = '01' (警告)

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

    存储函数不能返回警告,因为 RETURN 语句导致函数返回时,清除诊断区域。因此,清除可能存在的警告(并将 warning_count 重置为 0)。

  • 类 = '02' (未找到)

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

  • 类 > '02' (异常)

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

  • 类 = '40'

    视为普通异常。