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,則對診斷區域的大小或內容沒有立即影響。