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 |
| |
+----------+