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 擴充功能 MYSQL_ERRNO
之外,所有項目都是標準 SQL。關於這些項目的更多資訊,請參閱 第 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'
視為一般的例外狀況。