Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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)

SIGNAL 是返回错误的方式。 SIGNAL 提供了错误信息给处理程序、应用程序的外部部分或客户端。它还提供了错误的特征(错误号、SQLSTATE 值、消息)。没有 SIGNAL,需要使用工作-around方法,如故意引用不存在的表来导致一个程序返回错误。

不需要任何权限来执行 SIGNAL 语句。

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

SIGNAL 语句中的 condition_value 表示要返回的错误值。它可以是一个 SQLSTATE 值(5个字符的字符串字面量)或一个 condition_name,该名称引用之前使用 DECLARE ... CONDITION 声明的命名条件(见 第15.6.7.1节,“DECLARE ... CONDITION 语句”)。

一个 SQLSTATE 值可以表示错误、警告或““not found.””。该值的前两个字符表示错误类别,详见 信号条件信息项。一些信号值会导致语句终止;见 信号对处理程序、游标和语句的影响

SQLSTATE 值对于SIGNAL 语句应该不以 '00' 开头,因为这样的值表示成功且无效用于错误 signaling。这是无论 SQLSTATE 值是在SIGNAL 语句中指定的还是在语句中引用的命名条件中指定的。如果值无效,将出现 Bad SQLSTATE 错误。

要 signal 一个通用的 SQLSTATE 值,可以使用 '45000',它表示“未处理的用户定义异常。

SIGNAL 语句可选地包括一个 SET 子句,该子句包含多个信号项目的列表,使用逗号分隔的 condition_information_item_name = simple_value_specification 分配语句。

每个 condition_information_item_name 可以在 SET 子句中指定最多一次。否则,将出现 Duplicate condition information item 错误。

有效的 simple_value_specification 设定符可以使用存储程序或函数参数、存储程序本地变量、用户定义变量、系统变量或字面值指定。字符字面值可能包含 _charset 引入符。

有关可接受的 condition_information_item_name 值的信息,请参阅Signal Condition Information Items

以下过程根据 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() signal 一个警告,因为 SQLSTATE 值以 '01' 开头是警告类信号。这不终止过程,可以使用SHOW WARNINGS 在过程返回后查看警告。

如果 pval 是 1,p() signal 错误并设置 MESSAGE_TEXT 条件信息项目。错误终止过程,并返回错误信息。

如果 pval 是 2,p() signal 同一个错误,但是使用命名条件指定 SQLSTATE 值。

如果 pval 是任何其他值,p() 首先 signal 一个警告,并设置错误信息项目。这个警告不终止过程,所以执行继续,然后 p() signal 错误。错误终止过程,并返回错误信息。

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 值,该值将用来.signal 指定的条件。示例:

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'

关于服务器在条件出现时选择处理器的信息,请参阅 Section 15.6.7.6, “Scope Rules for Handlers”

可以在异常处理器中引发信号:

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,except 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值的命名条件。一个SQLSTATE值的前两个字符是其类别,类别确定了诊断信息项的默认值:

  • 类别='00'(成功)

    类别'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的目的是明确地引发用户生成的错误,因此信号永不被忽略。

以下描述中,unhandled表示没有为信号的SQLSTATE值定义了处理程序,以DECLARE ... HANDLER语句。

  • Class = '00' (成功)

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

  • Class = '01' (警告)

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

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

  • Class = '02' (未找到)

    NOT FOUND处理程序捕捉信号。如果信号在存储函数中未处理,语句结束。

  • Class > '02' (异常)

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

  • Class = '40'

    视为普通异常。