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 语句生成诊断信息,这些信息填充诊断区域。 GET DIAGNOSTICS
语句使应用程序能够检查此信息。(您也可以使用 SHOW WARNINGS
或 SHOW ERRORS
来查看条件或错误。)
执行 GET DIAGNOSTICS
不需要任何特殊权限。
关键字 CURRENT
表示从当前诊断区域检索信息。关键字 STACKED
表示从第二个诊断区域检索信息,该区域仅在当前上下文是条件处理程序时可用。如果没有给出任何关键字,则默认使用当前诊断区域。
在存储程序内的处理程序中,通常使用 GET DIAGNOSTICS
语句。这是一个 MySQL 扩展,它允许在处理程序上下文之外使用 GET [CURRENT] DIAGNOSTICS
来检查任何 SQL 语句的执行情况。例如,如果您调用 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' |
+-------+------------------------------------+
此扩展仅适用于当前诊断区域。它不适用于第二个诊断区域,因为只有在当前上下文为条件处理程序时才允许使用 GET STACKED DIAGNOSTICS
。如果不是这种情况,就会发生 GET STACKED DIAGNOSTICS when handler not active
错误。
有关诊断区域的描述,请参见 第 15.6.7.7 节,“MySQL 诊断区域”。简而言之,它包含两种信息
语句信息,例如发生的条件数量或受影响的行数。
条件信息,例如错误代码和消息。如果语句引发多个条件,则诊断区域的这一部分为每个条件都设有一个条件区域。如果语句没有引发任何条件,则诊断区域的这一部分为空。
对于生成三个条件的语句,诊断区域将包含如下所示的语句和条件信息
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
可以获取语句或条件信息,但不能在同一语句中同时获取两者
要获取语句信息,请将所需的语句项检索到目标变量中。此
GET DIAGNOSTICS
实例将可用的条件数量和受影响的行数分配给用户变量@p1
和@p2
GET DIAGNOSTICS @p1 = NUMBER, @p2 = ROW_COUNT;
要获取条件信息,请指定条件编号,并将所需的条件项检索到目标变量中。此
GET DIAGNOSTICS
实例将 SQLSTATE 值和错误消息分配给用户变量@p3
和@p4
GET DIAGNOSTICS CONDITION 1 @p3 = RETURNED_SQLSTATE, @p4 = MESSAGE_TEXT;
检索列表指定一个或多个以逗号分隔的
赋值。每个赋值都命名一个目标变量,以及一个 target
= item_name
statement_information_item_name
或 condition_information_item_name
指定符,具体取决于语句是检索语句信息还是条件信息。
用于存储项目信息的有效 target
指定符可以是存储过程或函数参数、使用 DECLARE
声明的存储程序局部变量或用户定义的变量。
有效 condition_number
指定符可以是存储过程或函数参数、使用 DECLARE
声明的存储程序局部变量、用户定义的变量、系统变量或文字。字符文字可以包含 _charset
引入器。如果条件编号不在 1 到具有信息的条件区域数量的范围内,就会出现警告。在这种情况下,警告将添加到诊断区域,但不会清除它。
当出现条件时,MySQL 不会填充 GET DIAGNOSTICS
识别的所有条件项。例如
mysql> GET DIAGNOSTICS CONDITION 1
@p5 = SCHEMA_NAME, @p6 = TABLE_NAME;
mysql> SELECT @p5, @p6;
+------+------+
| @p5 | @p6 |
+------+------+
| | |
+------+------+
在标准 SQL 中,如果有多个条件,第一个条件将与先前 SQL 语句返回的 SQLSTATE
值相关联。在 MySQL 中,这不是保证的。要获取主错误,您不能这样做
GET DIAGNOSTICS CONDITION 1 @errno = MYSQL_ERRNO;
相反,请先检索条件计数,然后使用它来指定要检查的条件编号
GET DIAGNOSTICS @cno = NUMBER;
GET DIAGNOSTICS CONDITION @cno @errno = MYSQL_ERRNO;
有关允许的语句和条件信息项以及在发生条件时填充哪些项的信息,请参见 诊断区域信息项。
以下示例使用 GET DIAGNOSTICS
和存储过程上下文中的异常处理程序来评估插入操作的结果。如果插入成功,则该过程将使用 GET DIAGNOSTICS
获取受影响的行数。这表明您可以多次使用 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;
假设 t1.int_col
是一个整数列,声明为 NOT NULL
。该过程在分别调用以插入非 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 |
+-------------------------------------------------------------------------+
当条件处理程序激活时,会将诊断区域堆栈进行推送
第一个(当前)诊断区域将成为第二个(堆叠)诊断区域,并创建一个新的当前诊断区域,作为它的副本。
GET [CURRENT] DIAGNOSTICS
和GET STACKED DIAGNOSTICS
可在处理程序内使用,以访问当前和堆叠诊断区域的内容。最初,两个诊断区域都返回相同的结果,因此可以从当前诊断区域获取有关激活处理程序的条件的信息,只要您在处理程序中未执行任何更改其当前诊断区域的语句。
但是,在处理程序中执行的语句可能会修改当前诊断区域,根据正常规则清除和设置其内容(请参见 如何清除和填充诊断区域)。
获取有关激活处理程序的条件的更可靠的方法是使用堆叠诊断区域,该区域不能被在处理程序中执行的语句修改,除非是
RESIGNAL
。有关何时设置和清除当前诊断区域的信息,请参见 第 15.6.7.7 节,“MySQL 诊断区域”。
以下示例显示了如何在处理程序内使用 GET STACKED DIAGNOSTICS
来获取有关已处理异常的信息,即使当前诊断区域已由处理程序语句修改。
在存储过程 p()
内,我们尝试将两个值插入到包含 TEXT NOT NULL
列的表中。第一个值是非 NULL
字符串,第二个是 NULL
。该列不允许 NULL
值,因此第一个插入操作成功,但第二个操作会导致异常。该过程包含一个异常处理程序,将尝试插入 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;
当处理程序激活时,当前诊断区域的副本将被推送到诊断区域堆栈。处理程序首先显示当前和堆叠诊断区域的内容,它们最初都是一样的
+---------------------------------+-------+----------------------------+
| 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 |
+---------------------------------+-------+----------------------------+
在 GET DIAGNOSTICS
语句之后执行的语句可能会重置当前诊断区域。语句可能会重置当前诊断区域。例如,处理程序将 NULL
插入操作映射到空字符串插入操作,并显示结果。新的插入操作成功并清除当前诊断区域,但堆叠诊断区域保持不变,并且仍然包含有关激活处理程序的条件的信息
+----------------------------------------------+
| op |
+----------------------------------------------+
| mapped insert succeeded, current DA is empty |
+----------------------------------------------+
+--------------------------------+-------+----------------------------+
| op | errno | msg |
+--------------------------------+-------+----------------------------+
| stacked DA after mapped insert | 1048 | Column 'c1' cannot be null |
+--------------------------------+-------+----------------------------+
当条件处理程序结束时,其当前诊断区域将从堆栈中弹出,堆叠诊断区域将成为存储过程中的当前诊断区域。
在过程返回后,该表将包含两行。空行来自尝试插入 NULL
的操作,该操作已映射到空字符串插入操作
+----------+
| c1 |
+----------+
| string 1 |
| |
+----------+