SQL 陳述式會產生診斷資訊,這些資訊會填入診斷區。標準 SQL 有一個診斷區堆疊,其中包含每個巢狀執行內容的診斷區。標準 SQL 也支援 GET STACKED DIAGNOSTICS
語法,用於在條件處理常式執行期間參考第二個診斷區。
以下討論說明 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()
函數的值相同(請參閱第 14.15 節,「資訊函數」)。
診斷區域的條件資訊部分包含每個條件的條件區域。條件區域的編號從 1 到 NUMBER
陳述式條件項目值。如果 NUMBER
為 0,則沒有條件區域。
每個條件區域都包含下列清單中的項目。除了 MYSQL_ERRNO
之外,所有項目都是標準 SQL,MYSQL_ERRNO
是 MySQL 的擴充功能。這些定義適用於由訊號以外的其他方式產生的條件(也就是由 SIGNAL
或 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
為'ISO 9075'
或RETURNED_SQLSTATE
以'000'
結尾,則SUBCLASS_ORIGIN
為'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
(或 RESIGNAL
)陳述式填入診斷區域,其 SET
子句可以為任何條件資訊項目(除了 RETURNED_SQLSTATE
之外)指派任何對項目資料類型合法的的值。SIGNAL
也會設定 RETURNED_SQLSTATE
值,但不會直接在其 SET
子句中設定。該值來自 SIGNAL
陳述式的 SQLSTATE
引數。
SIGNAL
也會設定陳述式資訊項目。它將 NUMBER
設定為 1。對於錯誤,它將 ROW_COUNT
設定為 -1,否則設定為 0。
非診斷 SQL 陳述式會自動填入診斷區域,其內容可以使用 SIGNAL
和 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
而發生的例外情況。然後,彈出診斷區域中的任何警告或錯誤條件都會新增至目前的診斷區域,但對於觸發程序,只會新增錯誤。當儲存的程式結束時,呼叫者會在目前的診斷區域中看到這些條件。
在儲存的程式中執行條件處理常式
當由於條件處理常式啟動而發生推入時,堆疊的診斷區域是在推入之前在儲存的程式中目前的區域。新的現在目前的診斷區域是處理常式的目前診斷區域。可以在處理常式中使用
GET [CURRENT] DIAGNOSTICS
和GET STACKED DIAGNOSTICS
來存取目前(處理常式)和堆疊(儲存的程式)診斷區域的內容。最初,它們會傳回相同的結果,但是處理常式中執行的陳述式會修改目前的診斷區域,根據正常規則清除和設定其內容(請參閱診斷區域如何清除和填入)。除了RESIGNAL
之外,處理常式中執行的陳述式無法修改堆疊的診斷區域。如果處理常式成功執行,則會彈出目前(處理常式)診斷區域,並且堆疊(儲存的程式)診斷區域再次成為目前的診斷區域。在處理常式執行期間新增至處理常式診斷區域的條件會新增至目前的診斷區域。
執行
RESIGNAL
RESIGNAL
陳述式會傳遞在儲存的程式內的複合陳述式中執行條件處理常式時可用的錯誤條件資訊。RESIGNAL
可以在傳遞某些或所有資訊之前變更它,並根據第 15.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,warning_count
為 20,而 error_count
為 12。
修改 max_error_count
的值,直到下次嘗試修改診斷區域時才會生效。如果診斷區域包含 10 個條件區域,且 max_error_count
設定為 5,則對診斷區域的大小或內容不會立即產生影響。