SIGNAL condition_value
[SET signal_information_item
[, signal_information_item] ...]
condition_value: {
SQLSTATE [VALUE] sqlstate_value
| condition_name
}
signal_information_item:
condition_information_item_name = simple_value_specification
condition_information_item_name: {
CLASS_ORIGIN
| SUBCLASS_ORIGIN
| MESSAGE_TEXT
| MYSQL_ERRNO
| CONSTRAINT_CATALOG
| CONSTRAINT_SCHEMA
| CONSTRAINT_NAME
| CATALOG_NAME
| SCHEMA_NAME
| TABLE_NAME
| COLUMN_NAME
| CURSOR_NAME
}
condition_name, simple_value_specification:
(see following discussion)
SIGNAL
是「傳回」錯誤的方式。SIGNAL
將錯誤資訊提供給處理常式、應用程式的外部部分或客戶端。此外,它還能控制錯誤的特性(錯誤編號、SQLSTATE
值、訊息)。如果沒有 SIGNAL
,就必須求助於權宜之計,例如故意參考不存在的資料表,以導致常式傳回錯誤。
執行 SIGNAL
語句不需要任何權限。
若要從診斷區擷取資訊,請使用 GET DIAGNOSTICS
語句(請參閱第 15.6.7.3 節,「GET DIAGNOSTICS 語句」)。如需有關診斷區的資訊,請參閱第 15.6.7.7 節,「MySQL 診斷區」。
在 SIGNAL
陳述式中的 condition_value
表示要傳回的錯誤值。它可以是 SQLSTATE
值(一個 5 個字元的字串文字),或是一個 condition_name
,指的是先前用 DECLARE ... CONDITION
定義的具名條件(請參閱第 15.6.7.1 節,「DECLARE ... CONDITION 陳述式」)。
SQLSTATE
值可以表示錯誤、警告或「「找不到」」。該值的前兩個字元表示其錯誤類別,如訊號條件資訊項目中所述。某些訊號值會導致陳述式終止;請參閱訊號對處理常式、游標和陳述式的影響。
SIGNAL
陳述式的 SQLSTATE
值不應以 '00'
開頭,因為此類值表示成功,且不適用於發出錯誤訊號。無論 SQLSTATE
值是在 SIGNAL
陳述式中直接指定,還是在陳述式中參照的具名條件中指定,都是如此。如果值無效,則會發生 Bad SQLSTATE
錯誤。
若要發出一般 SQLSTATE
值訊號,請使用 '45000'
,這表示「「未處理的使用者定義例外狀況」」。
SIGNAL
陳述式可以選擇性地包含 SET
子句,其中包含多個訊號項目,以逗號分隔的 condition_information_item_name
= simple_value_specification
指派清單。
每個 condition_information_item_name
在 SET
子句中只能指定一次。否則,會發生 Duplicate condition information item
錯誤。
可以使用預存程序或函式參數、用 DECLARE
宣告的預存程式區域變數、使用者定義的變數、系統變數或文字指定有效的 simple_value_specification
指定符。字元文字可以包含 _charset
引導詞。
如需關於允許的 condition_information_item_name
值的資訊,請參閱訊號條件資訊項目。
以下程序根據輸入參數 pval
的值發出錯誤或警告訊號
CREATE PROCEDURE p (pval INT)
BEGIN
DECLARE specialty CONDITION FOR SQLSTATE '45000';
IF pval = 0 THEN
SIGNAL SQLSTATE '01000';
ELSEIF pval = 1 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'An error occurred';
ELSEIF pval = 2 THEN
SIGNAL specialty
SET MESSAGE_TEXT = 'An error occurred';
ELSE
SIGNAL SQLSTATE '01000'
SET MESSAGE_TEXT = 'A warning occurred', MYSQL_ERRNO = 1000;
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'An error occurred', MYSQL_ERRNO = 1001;
END IF;
END;
如果 pval
為 0,p()
會發出警告訊號,因為以 '01'
開頭的 SQLSTATE
值是警告類別中的訊號。警告不會終止程序,並且可以在程序返回後使用 SHOW WARNINGS
檢視。
如果 pval
為 1,p()
會發出錯誤訊號,並設定 MESSAGE_TEXT
條件資訊項目。該錯誤會終止程序,並且文字會與錯誤資訊一起返回。
如果 pval
為 2,則會發出相同的錯誤訊號,但在此情況下,SQLSTATE
值是使用具名條件指定的。
如果 pval
為任何其他值,p()
會先發出警告訊號,並設定訊息文字和錯誤編號條件資訊項目。此警告不會終止程序,因此執行會繼續,然後 p()
會發出錯誤訊號。該錯誤會終止程序。警告設定的訊息文字和錯誤編號會被錯誤設定的值取代,這些值會與錯誤資訊一起返回。
SIGNAL
通常在預存程式中使用,但它是 MySQL 擴充功能,允許在處理常式內容之外使用。例如,如果您調用 mysql 客戶端程式,則可以在提示符號處輸入下列任何陳述式
SIGNAL SQLSTATE '77777';
CREATE TRIGGER t_bi BEFORE INSERT ON t
FOR EACH ROW SIGNAL SQLSTATE '77777';
CREATE EVENT e ON SCHEDULE EVERY 1 SECOND
DO SIGNAL SQLSTATE '77777';
SIGNAL
根據下列規則執行
如果 SIGNAL
陳述式指出特定的 SQLSTATE
值,則該值會用於發出指定的條件訊號。範例
CREATE PROCEDURE p (divisor INT)
BEGIN
IF divisor = 0 THEN
SIGNAL SQLSTATE '22012';
END IF;
END;
如果 SIGNAL
陳述式使用具名條件,則該條件必須在適用於 SIGNAL
陳述式的範圍內宣告,並且必須使用 SQLSTATE
值定義,而不是 MySQL 錯誤編號。範例
CREATE PROCEDURE p (divisor INT)
BEGIN
DECLARE divide_by_zero CONDITION FOR SQLSTATE '22012';
IF divisor = 0 THEN
SIGNAL divide_by_zero;
END IF;
END;
如果具名條件不存在於 SIGNAL
陳述式的範圍內,則會發生 Undefined CONDITION
錯誤。
如果 SIGNAL
參照的具名條件是用 MySQL 錯誤編號而不是 SQLSTATE
值定義的,則會發生 SIGNAL/RESIGNAL can only use a CONDITION defined with SQLSTATE
錯誤。以下陳述式會導致該錯誤,因為具名條件與 MySQL 錯誤編號相關聯
DECLARE no_such_table CONDITION FOR 1051;
SIGNAL no_such_table;
如果在不同的範圍中多次宣告具有指定名稱的條件,則適用於最局部範圍的宣告。請考慮以下程序
CREATE PROCEDURE p (divisor INT)
BEGIN
DECLARE my_error CONDITION FOR SQLSTATE '45000';
IF divisor = 0 THEN
BEGIN
DECLARE my_error CONDITION FOR SQLSTATE '22012';
SIGNAL my_error;
END;
END IF;
SIGNAL my_error;
END;
如果 divisor
為 0,則會執行第一個 SIGNAL
陳述式。會套用最內部的 my_error
條件宣告,引發 SQLSTATE
'22012'
。
如果 divisor
不為 0,則會執行第二個 SIGNAL
陳述式。會套用最外部的 my_error
條件宣告,引發 SQLSTATE
'45000'
。
如需關於伺服器在發生條件時如何選擇處理常式的資訊,請參閱第 15.6.7.6 節,「處理常式的範圍規則」。
可以在例外處理常式中引發訊號
CREATE PROCEDURE p ()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SIGNAL SQLSTATE VALUE '99999'
SET MESSAGE_TEXT = 'An error occurred';
END;
DROP TABLE no_such_table;
END;
CALL p()
會到達 DROP TABLE
陳述式。沒有名為 no_such_table
的資料表,因此會啟動錯誤處理常式。錯誤處理常式會銷毀原始錯誤(「「沒有此類資料表」」),並以 SQLSTATE
'99999'
和訊息 An error occurred
產生一個新的錯誤。
下表列出可以在 SIGNAL
(或 RESIGNAL
) 陳述式中設定的診斷區域條件資訊項目的名稱。除了 MYSQL_ERRNO
外,所有項目都是標準 SQL,MYSQL_ERRNO
是 MySQL 擴充功能。如需關於這些項目的詳細資訊,請參閱第 15.6.7.7 節,「MySQL 診斷區域」。
Item Name Definition
--------- ----------
CLASS_ORIGIN VARCHAR(64)
SUBCLASS_ORIGIN VARCHAR(64)
CONSTRAINT_CATALOG VARCHAR(64)
CONSTRAINT_SCHEMA VARCHAR(64)
CONSTRAINT_NAME VARCHAR(64)
CATALOG_NAME VARCHAR(64)
SCHEMA_NAME VARCHAR(64)
TABLE_NAME VARCHAR(64)
COLUMN_NAME VARCHAR(64)
CURSOR_NAME VARCHAR(64)
MESSAGE_TEXT VARCHAR(128)
MYSQL_ERRNO SMALLINT UNSIGNED
字元項目的字元集為 UTF-8。
在 SIGNAL
陳述式中,將 NULL
指派給條件資訊項目是違法的。
SIGNAL
陳述式總是指定 SQLSTATE
值,可以是直接指定,或是間接參照使用 SQLSTATE
值定義的具名條件。SQLSTATE
值的前兩個字元是其類別,而類別會決定條件資訊項目的預設值
類別 =
'00'
(成功)非法。以
'00'
開頭的SQLSTATE
值表示成功,且不適用於SIGNAL
。類別 =
'01'
(警告)MESSAGE_TEXT = 'Unhandled user-defined warning condition'; MYSQL_ERRNO = ER_SIGNAL_WARN
類別 =
'02'
(找不到)MESSAGE_TEXT = 'Unhandled user-defined not found condition'; MYSQL_ERRNO = ER_SIGNAL_NOT_FOUND
類別 >
'02'
(例外狀況)MESSAGE_TEXT = 'Unhandled user-defined exception condition'; MYSQL_ERRNO = ER_SIGNAL_EXCEPTION
對於合法的類別,其他條件資訊項目會設定如下
CLASS_ORIGIN = SUBCLASS_ORIGIN = '';
CONSTRAINT_CATALOG = CONSTRAINT_SCHEMA = CONSTRAINT_NAME = '';
CATALOG_NAME = SCHEMA_NAME = TABLE_NAME = COLUMN_NAME = '';
CURSOR_NAME = '';
在執行 SIGNAL
後可存取的錯誤值是 SIGNAL
陳述式引發的 SQLSTATE
值以及 MESSAGE_TEXT
和 MYSQL_ERRNO
項目。這些值可從 C API 取得
mysql_sqlstate()
會傳回SQLSTATE
值。mysql_errno()
會傳回MYSQL_ERRNO
值。mysql_error()
會傳回MESSAGE_TEXT
值。
在 SQL 層級,SHOW WARNINGS
和 SHOW ERRORS
的輸出會在 Code
和 Message
欄中指出 MYSQL_ERRNO
和 MESSAGE_TEXT
值。
若要從診斷區擷取資訊,請使用 GET DIAGNOSTICS
語句(請參閱第 15.6.7.3 節,「GET DIAGNOSTICS 語句」)。如需有關診斷區的資訊,請參閱第 15.6.7.7 節,「MySQL 診斷區」。
訊號對於語句執行的影響取決於訊號的類別。類別決定了錯誤的嚴重程度。MySQL 會忽略 sql_mode
系統變數的值;特別是,嚴格 SQL 模式並不重要。MySQL 也會忽略 IGNORE
:SIGNAL
的目的是明確引發使用者產生的錯誤,因此訊號永遠不會被忽略。
在以下描述中,「未處理」表示沒有使用 DECLARE ... HANDLER
為已發出訊號的 SQLSTATE
值定義處理常式。
類別 =
'00'
(成功)非法。以
'00'
開頭的SQLSTATE
值表示成功,且不適用於SIGNAL
。類別 =
'01'
(警告)warning_count
系統變數的值會增加。SHOW WARNINGS
會顯示訊號。SQLWARNING
處理常式會捕獲訊號。警告無法從儲存函數傳回,因為導致函數傳回的
RETURN
語句會清除診斷區域。因此,該語句會清除可能存在於該區域的任何警告(並將warning_count
重置為 0)。類別 =
'02'
(找不到)NOT FOUND
處理常式會捕獲訊號。對游標沒有影響。如果訊號在儲存函數中未處理,則語句會結束。類別 >
'02'
(例外狀況)SQLEXCEPTION
處理常式會捕獲訊號。如果訊號在儲存函數中未處理,則語句會結束。類別 =
'40'
被視為一般的例外狀況。