13.6.7.3 GET DIAGNOSTICS Statement语句

GET [CURRENT | STACKED] DIAGNOSTICS {
statement_information_item
    [, statement_information_item] ...
  | CONDITION condition_number
condition_information_item
    [, condition_information_item] ...
}
statement_information_item:
target = statement_information_item_name
condition_information_item:
target = condition_information_item_name
statement_information_item_name: {
    NUMBER
  | ROW_COUNT
}
condition_information_item_name: {
    CLASS_ORIGIN
  | SUBCLASS_ORIGIN
  | RETURNED_SQLSTATE
  | MESSAGE_TEXT
  | MYSQL_ERRNO
  | CONSTRAINT_CATALOG
  | CONSTRAINT_SCHEMA
  | CONSTRAINT_NAME
  | CATALOG_NAME
  | SCHEMA_NAME
  | TABLE_NAME
  | COLUMN_NAME
  | CURSOR_NAME
}
condition_number, target:
    (see following discussion)

SQL statements produce diagnostic information that populates the diagnostics area. SQL语句生成填充诊断区域的诊断信息。The GET DIAGNOSTICS statement enables applications to inspect this information.GET DIAGNOSTICS语句允许应用程序检查此信息。 (You can also use SHOW WARNINGS or SHOW ERRORS to see conditions or errors.)(也可以使用SHOW WARNINGSSHOW ERRORS来查看条件或错误。)

No special privileges are required to execute GET DIAGNOSTICS.执行GET DIAGNOSTICS不需要特殊权限。

The keyword CURRENT means to retrieve information from the current diagnostics area. 关键字CURRENT表示从当前诊断区域检索信息。The keyword STACKED means to retrieve information from the second diagnostics area, which is available only if the current context is a condition handler. 关键字STACKED意味着从第二个诊断区域检索信息,该区域仅在当前上下文是条件处理程序时可用。If neither keyword is given, the default is to use the current diagnostics area.如果两个关键字都没有给出,默认情况下使用当前诊断区域。

The GET DIAGNOSTICS statement is typically used in a handler within a stored program. GET DIAGNOSTICS语句通常用于存储程序中的处理程序中。It is a MySQL extension that GET [CURRENT] DIAGNOSTICS is permitted outside handler context to check the execution of any SQL statement. 它是一个MySQL扩展,允许GET [CURRENT] DIAGNOSTICS在处理程序上下文之外检查任何SQL语句的执行情况。For example, if you invoke the mysql client program, you can enter these statements at the prompt:例如,如果调用mysql客户端程序,可以在提示符处输入以下语句:

mysql> DROP TABLE test.no_such_table;
ERROR 1051 (42S02): Unknown table 'test.no_such_table'
mysql> GET DIAGNOSTICS CONDITION 1
@p1 = RETURNED_SQLSTATE, @p2 = MESSAGE_TEXT;
mysql> SELECT @p1, @p2;
+-------+------------------------------------+
| @p1   | @p2                                |
+-------+------------------------------------+
| 42S02 | Unknown table 'test.no_such_table' |
+-------+------------------------------------+

This extension applies only to the current diagnostics area. 此扩展仅适用于当前诊断区域。It does not apply to the second diagnostics area because GET STACKED DIAGNOSTICS is permitted only if the current context is a condition handler. 它不适用于第二个诊断区域,因为只有当当前上下文是条件处理程序时,才允许GET STACKED DIAGNOSTICSIf that is not the case, a GET STACKED DIAGNOSTICS when handler not active error occurs.如果情况并非如此,则会发生GET STACKED DIAGNOSTICS when handler not active(处理程序未激活时获取堆叠诊断)错误。

For a description of the diagnostics area, see Section 13.6.7.7, “The MySQL Diagnostics Area”. 有关诊断区域的描述,请参阅第13.6.7.7节,“MySQL诊断区域”Briefly, it contains two kinds of information:简而言之,它包含两种信息:

For a statement that produces three conditions, the diagnostics area contains statement and condition information like this:对于产生三个条件的语句,诊断区域包含如下语句和条件信息:

Statement information:
  row count
  ... other statement information items ...
Condition area list:
  Condition area 1:
    error code for condition 1
    error message for condition 1
    ... other condition information items ...
  Condition area 2:
    error code for condition 2:
    error message for condition 2
    ... other condition information items ...
  Condition area 3:
    error code for condition 3
    error message for condition 3
    ... other condition information items ...

GET DIAGNOSTICS can obtain either statement or condition information, but not both in the same statement:GET DIAGNOSTICS可以获取语句或条件信息,但不能在同一语句中同时获取这两种信息:

The retrieval list specifies one or more target = item_name assignments, separated by commas. 检索列表指定一个或多个target = item_name分配,用逗号分隔。Each assignment names a target variable and either a statement_information_item_name or condition_information_item_name designator, depending on whether the statement retrieves statement or condition information.每个赋值都命名一个目标变量和statement_information_item_namecondition_information_item_name指示符,具体取决于该语句检索的是语句还是条件信息。

Valid target designators for storing item information can be stored procedure or function parameters, stored program local variables declared with DECLARE, or user-defined variables.用于存储项信息的有效target标识符可以是存储过程或函数参数、用DECLARE声明的存储程序局部变量或用户定义的变量。

Valid condition_number designators can be stored procedure or function parameters, stored program local variables declared with DECLARE, user-defined variables, system variables, or literals. 有效condition_number指示符可以是存储过程或函数参数、用DECLARE声明的存储程序局部变量、用户定义变量、系统变量或文字。A character literal may include a _charset introducer. 字符文字可能包括_charset介绍人。A warning occurs if the condition number is not in the range from 1 to the number of condition areas that have information. 如果条件编号不在1到包含信息的条件区域数量的范围内,则会出现警告。In this case, the warning is added to the diagnostics area without clearing it.在这种情况下,警告会添加到诊断区域,而不会清除它。

When a condition occurs, MySQL does not populate all condition items recognized by GET DIAGNOSTICS. 当出现条件时,MySQL不会填充GET DIAGNOSTICS识别的所有条件项。For example:例如:

mysql> GET DIAGNOSTICS CONDITION 1
@p5 = SCHEMA_NAME, @p6 = TABLE_NAME;
mysql> SELECT @p5, @p6;
+------+------+
| @p5  | @p6  |
+------+------+
|      |      |
+------+------+

In standard SQL, if there are multiple conditions, the first condition relates to the SQLSTATE value returned for the previous SQL statement. 在标准SQL中,如果有多个条件,第一个条件与前一条SQL语句返回的SQLSTATE值有关。In MySQL, this is not guaranteed. 在MySQL中,这并不能保证。To get the main error, you cannot do this:要获取主要错误,您不能执行以下操作:

GET DIAGNOSTICS CONDITION 1 @errno = MYSQL_ERRNO;

Instead, retrieve the condition count first, then use it to specify which condition number to inspect:相反,首先检索条件计数,然后使用它指定要检查的条件编号:

GET DIAGNOSTICS @cno = NUMBER;
GET DIAGNOSTICS CONDITION @cno @errno = MYSQL_ERRNO;

For information about permissible statement and condition information items, and which ones are populated when a condition occurs, see Diagnostics Area Information Items.有关允许的语句和条件信息项的信息,以及条件发生时填充的信息,请参阅诊断区域信息项

Here is an example that uses GET DIAGNOSTICS and an exception handler in stored procedure context to assess the outcome of an insert operation. 下面是一个示例,它在存储过程上下文中使用GET DIAGNOSTICS和异常处理程序来评估插入操作的结果。If the insert was successful, the procedure uses GET DIAGNOSTICS to get the rows-affected count. 如果插入成功,该过程将使用GET DIAGNOSTICS获取受影响的行数。This shows that you can use GET DIAGNOSTICS multiple times to retrieve information about a statement as long as the current diagnostics area has not been cleared.这表明,只要当前诊断区域尚未清除,就可以多次使用GET DIAGNOSTICS来检索有关语句的信息。

CREATE PROCEDURE do_insert(value INT)
BEGIN
  -- Declare variables to hold diagnostics area information
  DECLARE code CHAR(5) DEFAULT '00000';
  DECLARE msg TEXT;
  DECLARE nrows INT;
  DECLARE result TEXT;
  -- Declare exception handler for failed insert
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
    BEGIN
      GET DIAGNOSTICS CONDITION 1
        code = RETURNED_SQLSTATE, msg = MESSAGE_TEXT;
    END;

  -- Perform the insert
  INSERT INTO t1 (int_col) VALUES(value);
  -- Check whether the insert was successful
  IF code = '00000' THEN
    GET DIAGNOSTICS nrows = ROW_COUNT;
    SET result = CONCAT('insert succeeded, row count = ',nrows);
  ELSE
    SET result = CONCAT('insert failed, error = ',code,', message = ',msg);
  END IF;
  -- Say what happened
  SELECT result;
END;

Suppose that t1.int_col is an integer column that is declared as NOT NULL. 假设t1.int_col是一个声明为NOT NULL的整数列。The procedure produces these results when invoked to insert non-NULL and NULL values, respectively:调用该过程分别插入非NULL值和NULL值时,会生成以下结果:

mysql> CALL do_insert(1);
+---------------------------------+
| result                          |
+---------------------------------+
| insert succeeded, row count = 1 |
+---------------------------------+

mysql> CALL do_insert(NULL);
+-------------------------------------------------------------------------+
| result                                                                  |
+-------------------------------------------------------------------------+
| insert failed, error = 23000, message = Column 'int_col' cannot be null |
+-------------------------------------------------------------------------+

When a condition handler activates, a push to the diagnostics area stack occurs:当条件处理程序激活时,会推送到诊断区域堆栈:

The next example shows how GET STACKED DIAGNOSTICS can be used within a handler to obtain information about the handled exception, even after the current diagnostics area has been modified by handler statements.下一个示例显示了如何在处理程序中使用GET STACKED DIAGNOSTICS来获取有关已处理异常的信息,即使当前诊断区域已被处理程序语句修改。

Within a stored procedure p(), we attempt to insert two values into a table that contains a TEXT NOT NULL column. 在存储过程p()中,我们尝试将两个值插入到包含TEXT NOT NULL列的表中。The first value is a non-NULL string and the second is NULL. 第一个值是非NULL字符串,第二个值是NULL字符串。The column prohibits NULL values, so the first insert succeeds but the second causes an exception. 该列禁止NULL值,因此第一次插入成功,但第二次插入导致异常。The procedure includes an exception handler that maps attempts to insert NULL into inserts of the empty string:该过程包括一个异常处理程序,该处理程序将插入NULL的尝试映射到空字符串的插入中:

DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 TEXT NOT NULL);
DROP PROCEDURE IF EXISTS p;
delimiter //
CREATE PROCEDURE p ()
BEGIN
  -- Declare variables to hold diagnostics area information
  DECLARE errcount INT;
  DECLARE errno INT;
  DECLARE msg TEXT;
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    -- Here the current DA is nonempty because no prior statements
    -- executing within the handler have cleared it
    GET CURRENT DIAGNOSTICS CONDITION 1
      errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'current DA before mapped insert' AS op, errno, msg;
    GET STACKED DIAGNOSTICS CONDITION 1
      errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'stacked DA before mapped insert' AS op, errno, msg;

    -- Map attempted NULL insert to empty string insert
    INSERT INTO t1 (c1) VALUES('');

    -- Here the current DA should be empty (if the INSERT succeeded),
    -- so check whether there are conditions before attempting to
    -- obtain condition information
    GET CURRENT DIAGNOSTICS errcount = NUMBER;
    IF errcount = 0
    THEN
      SELECT 'mapped insert succeeded, current DA is empty' AS op;
    ELSE
      GET CURRENT DIAGNOSTICS CONDITION 1
        errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
      SELECT 'current DA after mapped insert' AS op, errno, msg;
    END IF ;
    GET STACKED DIAGNOSTICS CONDITION 1
      errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'stacked DA after mapped insert' AS op, errno, msg;
  END;
  INSERT INTO t1 (c1) VALUES('string 1');
  INSERT INTO t1 (c1) VALUES(NULL);
END;
//
delimiter ;
CALL p();
SELECT * FROM t1;

When the handler activates, a copy of the current diagnostics area is pushed to the diagnostics area stack. 当处理程序激活时,当前诊断区域的副本被推送到诊断区域堆栈。The handler first displays the contents of the current and stacked diagnostics areas, which are both the same initially:处理程序首先显示当前和堆叠诊断区域的内容,这两个区域最初是相同的:

+---------------------------------+-------+----------------------------+
| op                              | errno | msg                        |
+---------------------------------+-------+----------------------------+
| current DA before mapped insert |  1048 | Column 'c1' cannot be null |
+---------------------------------+-------+----------------------------+

+---------------------------------+-------+----------------------------+
| op                              | errno | msg                        |
+---------------------------------+-------+----------------------------+
| stacked DA before mapped insert |  1048 | Column 'c1' cannot be null |
+---------------------------------+-------+----------------------------+

Statements executing after the GET DIAGNOSTICS statements may reset the current diagnostics area. GET DIAGNOSTICS语句之后执行的语句可能会重置当前诊断区域。statements may reset the current diagnostics area. 语句可能会重置当前诊断区域。For example, the handler maps the NULL insert to an empty-string insert and displays the result. 例如,处理程序将空插入映射为空字符串插入,并显示结果。The new insert succeeds and clears the current diagnostics area, but the stacked diagnostics area remains unchanged and still contains information about the condition that activated the handler:新的插入成功并清除当前的诊断区域,但堆叠的诊断区域保持不变,仍然包含有关激活处理程序的条件的信息:

+----------------------------------------------+
| op                                           |
+----------------------------------------------+
| mapped insert succeeded, current DA is empty |
+----------------------------------------------+

+--------------------------------+-------+----------------------------+
| op                             | errno | msg                        |
+--------------------------------+-------+----------------------------+
| stacked DA after mapped insert |  1048 | Column 'c1' cannot be null |
+--------------------------------+-------+----------------------------+

When the condition handler ends, its current diagnostics area is popped from the stack and the stacked diagnostics area becomes the current diagnostics area in the stored procedure.当条件处理程序结束时,其当前诊断区域将从堆栈中弹出,并且堆叠的诊断区域将成为存储过程中的当前诊断区域。

After the procedure returns, the table contains two rows. 过程返回后,该表包含两行。The empty row results from the attempt to insert NULL that was mapped to an empty-string insert:空行是由于尝试插入映射到空字符串插入的NULL导致的:

+----------+
| c1       |
+----------+
| string 1 |
|          |
+----------+

In the preceding example, the first two GET DIAGNOSTICS statements within the condition handler that retrieve information from the current and stacked diagnostics areas return the same values. 在前面的示例中,条件处理程序中从当前和堆叠的诊断区域检索信息的前两个GET DIAGNOSTICS语句返回相同的值。This is not the case if statements that reset the current diagnostics area execute earlier within the handler. 如果重置当前诊断区域的语句更早地在处理程序中执行,则情况并非如此。Suppose that p() is rewritten to place the DECLARE statements within the handler definition rather than preceding it:假设p()被重写,将DECLARE语句放在处理程序定义中,而不是放在它前面:

CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    -- Declare variables to hold diagnostics area information
    DECLARE errcount INT;
    DECLARE errno INT;
    DECLARE msg TEXT;
    GET CURRENT DIAGNOSTICS CONDITION 1
      errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'current DA before mapped insert' AS op, errno, msg;
    GET STACKED DIAGNOSTICS CONDITION 1
      errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'stacked DA before mapped insert' AS op, errno, msg;
...

In this case, the result is version dependent:在这种情况下,结果取决于版本:

To avoid this issue within a condition handler when seeking to obtain information about the condition that activated the handler, be sure to access the stacked diagnostics area, not the current diagnostics area.为了避免在条件处理程序中出现此问题,当试图获取激活处理程序的条件的信息时,请确保访问堆叠的诊断区域,而不是当前的诊断区域。