SQL 语句产生填充诊断区域的诊断信息。标准 SQL 有一个诊断区域堆栈,包含每个嵌套执行上下文的诊断区域。标准 SQL 还支持
GET STACKED
DIAGNOSTICS
在条件处理程序执行期间引用第二个诊断区域的语法。MySQL 从 MySQL 5.7 开始支持STACKED
关键字。在此之前,MySQL 不支持STACKED
; 有一个诊断区域包含来自最近写入它的语句的信息。
下面的讨论描述了MySQL中诊断区的结构,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 ...
诊断区包含语句和条件信息项。数字项目是整数。字符项的字符集是UTF-8。没有项目可以
NULL
。如果语句或条件项不是由填充诊断区域的语句设置的,则其值为 0 或空字符串,具体取决于项数据类型。
诊断区域的语句信息部分包含以下项目:
NUMBER
:一个整数,表示有信息的条件区域的数量。ROW_COUNT
:一个整数,表示受该语句影响的行数。ROW_COUNT
与函数具有相同的值ROW_COUNT()
(请参阅 第 12.16 节,“信息函数”)。
诊断区的条件信息部分包含每个条件的条件区域。条件区域从 1 到
NUMBER
语句条件项的值编号。如果
NUMBER
为 0,则没有条件区域。
每个条件区域都包含以下列表中的项目。所有项目都是标准 SQL,除了
MYSQL_ERRNO
,它是 MySQL 扩展。这些定义适用于非信号(即SIGNAL
or
RESIGNAL
语句)生成的条件。对于非信号条件,MySQL 仅填充那些未描述为始终为空的条件项。信号对条件区域的影响在后面描述。
CLASS_ORIGIN
:包含值类的字符串RETURNED_SQLSTATE
。如果该RETURNED_SQLSTATE
值以 SQL 标准文档 ISO 9075-2(第 24.1 节,SQLSTATE)中定义的类值开头,CLASS_ORIGIN
则为'ISO 9075'
. 否则,CLASS_ORIGIN
是'MySQL'
。SUBCLASS_ORIGIN
: 包含RETURNED_SQLSTATE
值子类的字符串。如果CLASS_ORIGIN
is'ISO 9075'
或RETURNED_SQLSTATE
以 结尾'000'
,SUBCLASS_ORIGIN
则 is'ISO 9075'
。否则,SUBCLASS_ORIGIN
是'MySQL'
。RETURNED_SQLSTATE
:指示SQLSTATE
条件值的字符串。MESSAGE_TEXT
:一个字符串,指示条件的错误消息。MYSQL_ERRNO
:一个整数,指示条件的 MySQL 错误代码。CONSTRAINT_CATALOG
,CONSTRAINT_SCHEMA
,CONSTRAINT_NAME
:指示违反约束的目录、架构和名称的字符串。它们总是空的。CATALOG_NAME
,SCHEMA_NAME
,TABLE_NAME
,COLUMN_NAME
:表示与条件相关的目录、模式、表和列的字符串。它们总是空的。CURSOR_NAME
:表示游标名称的字符串。这总是空的。
对于特定错误的RETURNED_SQLSTATE
、
MESSAGE_TEXT
和
MYSQL_ERRNO
值,请参阅服务器错误消息参考。
如果SIGNAL
(or
RESIGNAL
) 语句填充诊断区域,则其SET
子句可以分配给任何条件信息项
,但RETURNED_SQLSTATE
对于项数据类型合法的任何值除外。SIGNAL
也设置RETURNED_SQLSTATE
值,但不是直接在它的SET
子句中。该值来自SIGNAL
语句
SQLSTATE
参数。
SIGNAL
还设置语句信息项。它设置NUMBER
为 1。ROW_COUNT
错误设置为 −1,否则设置为 0。
非诊断性 SQL 语句自动填充诊断区域,其内容可以使用
SIGNAL
and
RESIGNAL
语句显式设置。可以检查诊断区域GET
DIAGNOSTICS
以提取特定项目,或者使用
SHOW WARNINGS
或
SHOW ERRORS
查看条件或错误。
SQL语句清除和设置诊断区域如下:
当服务器在解析语句后开始执行它时,它会清除非诊断语句的诊断区域。诊断语句不会清除诊断区域。这些陈述是诊断性的:
如果语句引发条件,诊断区域将清除属于较早语句的条件。
GET DIAGNOSTICS
例外情况是由和 引发的条件RESIGNAL
被添加到诊断区域而不清除它。
因此,即使是在开始执行时通常不会清除诊断区域的语句也会在该语句引发条件时将其清除。
以下示例显示了各种语句对诊断区域的影响,SHOW
WARNINGS
用于显示有关存储在那里的条件的信息。
此DROP TABLE
语句清除诊断区域并在条件发生时填充它:
mysql> DROP TABLE IF EXISTS test.no_such_table;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> SHOW WARNINGS;
+-------+------+------------------------------------+
| Level | Code | Message |
+-------+------+------------------------------------+
| Note | 1051 | Unknown table 'test.no_such_table' |
+-------+------+------------------------------------+
1 row in set (0.00 sec)
此
SET
语句会产生一个错误,因此它会清除并填充诊断区域:
mysql> SET @x = @@x;
ERROR 1193 (HY000): Unknown system variable 'x'
mysql> SHOW WARNINGS;
+-------+------+-----------------------------+
| Level | Code | Message |
+-------+------+-----------------------------+
| Error | 1193 | Unknown system variable 'x' |
+-------+------+-----------------------------+
1 row in set (0.00 sec)
前面的
SET
语句产生了一个条件,因此 1 是此时唯一有效的条件编号GET
DIAGNOSTICS
。以下语句使用条件编号 2,它会生成一条警告,该警告会添加到诊断区域而不清除它:
mysql> GET DIAGNOSTICS CONDITION 2 @p = MESSAGE_TEXT;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> SHOW WARNINGS;
+-------+------+------------------------------+
| Level | Code | Message |
+-------+------+------------------------------+
| Error | 1193 | Unknown system variable 'xx' |
| Error | 1753 | Invalid condition number |
+-------+------+------------------------------+
2 rows in set (0.00 sec)
现在诊断区域中有两个条件,所以相同的GET DIAGNOSTICS
语句成功:
mysql> GET DIAGNOSTICS CONDITION 2 @p = MESSAGE_TEXT;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @p;
+--------------------------+
| @p |
+--------------------------+
| Invalid condition number |
+--------------------------+
1 row in set (0.01 sec)
当向诊断区域堆栈推送时,第一个(当前)诊断区域成为第二个(堆栈)诊断区域,并创建一个新的当前诊断区域作为它的副本。在以下情况下,诊断区域会被压入堆栈或从堆栈中弹出:
执行存储程序
推送发生在程序执行之前,弹出发生在程序执行之后。如果存储的程序在处理程序执行时结束,则可以弹出多个诊断区域;这是由于没有合适的处理程序或由于处理程序中的异常而发生
RETURN
的。弹出的诊断区域中的任何警告或错误条件都会添加到当前诊断区域,但对于触发器,只会添加错误。当存储的程序结束时,调用者会在其当前诊断区域中看到这些情况。
在存储程序中执行条件处理程序
当由于条件处理程序激活而发生推送时,堆栈诊断区域是推送之前存储程序中的当前区域。新的 now-current 诊断区域是处理程序的当前诊断区域。
GET [CURRENT] DIAGNOSTICS
并且GET STACKED DIAGNOSTICS
可以在处理程序中使用以访问当前(处理程序)和堆栈(存储程序)诊断区域的内容。最初,它们返回相同的结果,但在处理程序中执行的语句会修改当前诊断区域,根据正常规则清除和设置其内容(请参阅如何清除和填充诊断区域). 堆栈诊断区域不能被处理程序中执行的语句修改,exceptRESIGNAL
。如果处理程序成功执行,则弹出当前(处理程序)诊断区域并且堆栈(存储程序)诊断区域再次成为当前诊断区域。在处理程序执行期间添加到处理程序诊断区域的条件将添加到当前诊断区域。
执行
RESIGNAL
该
RESIGNAL
语句传递在存储程序内的复合语句中执行条件处理程序期间可用的错误条件信息。RESIGNAL
可能会在传递信息之前更改部分或全部信息,如 第 13.6.7.4 节“RESIGNAL 语句”中所述修改诊断堆栈。
某些系统变量控制或与诊断区域的某些方面相关:
max_error_count
控制诊断区域中条件区域的数量。如果出现比这个更多的条件,MySQL 会默默地丢弃多余条件的信息。(RESIGNAL
总是添加由添加的条件,并根据需要丢弃较旧的条件以腾出空间。)warning_count
指示发生的条件数。这包括错误、警告和注释。通常,NUMBER
和warning_count
是相同的。但是,随着生成的条件数超过max_error_count
, 的值warning_count
继续上升,而 由于没有其他条件存储在诊断区域中 ,因此NUMBER
仍处于上限。max_error_count
error_count
指示发生的错误数。该值包括 “未找到”和异常情况,但不包括警告和注释。就像warning_count
,它的价值可以超过max_error_count
。如果
sql_notes
系统变量设置为 0,则不存储注释且不递增warning_count
。
示例:如果max_error_count
是 10,则诊断区域最多可以包含 10 个条件区域。假设一条语句提出 20 个条件,其中 12 个是错误。在这种情况下,诊断区域包含前 10 个条件,
NUMBER
即 10、20
warning_count
和
error_count
12。
max_error_count
直到下一次尝试修改诊断区域
时,对值的更改才会
生效。如果诊断区域包含 10 个条件区域并
max_error_count
设置为 5,则不会立即影响诊断区域的大小或内容。