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'被視為一般的例外狀況。