文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 39.9Mb
PDF (A4) - 40.0Mb
手冊頁 (TGZ) - 258.5Kb
手冊頁 (Zip) - 365.5Kb
資訊 (Gzip) - 4.0Mb
資訊 (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  SIGNAL 語句

15.6.7.5 SIGNAL 語句

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 概觀

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_nameSET 子句中只能指定一次。否則,會發生 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_TEXTMYSQL_ERRNO 項目。這些值可從 C API 取得

在 SQL 層級,SHOW WARNINGSSHOW ERRORS 的輸出會在 CodeMessage 欄中指出 MYSQL_ERRNOMESSAGE_TEXT 值。

若要從診斷區擷取資訊,請使用 GET DIAGNOSTICS 語句(請參閱第 15.6.7.3 節,「GET DIAGNOSTICS 語句」)。如需有關診斷區的資訊,請參閱第 15.6.7.7 節,「MySQL 診斷區」

訊號對處理常式、游標和陳述式的影響

訊號對於語句執行的影響取決於訊號的類別。類別決定了錯誤的嚴重程度。MySQL 會忽略 sql_mode 系統變數的值;特別是,嚴格 SQL 模式並不重要。MySQL 也會忽略 IGNORESIGNAL 的目的是明確引發使用者產生的錯誤,因此訊號永遠不會被忽略。

在以下描述中,「未處理」表示沒有使用 DECLARE ... HANDLER 為已發出訊號的 SQLSTATE 值定義處理常式。

  • 類別 = '00' (成功)

    非法。以 '00' 開頭的 SQLSTATE 值表示成功,且不適用於 SIGNAL

  • 類別 = '01' (警告)

    warning_count 系統變數的值會增加。SHOW WARNINGS 會顯示訊號。SQLWARNING 處理常式會捕獲訊號。

    警告無法從儲存函數傳回,因為導致函數傳回的 RETURN 語句會清除診斷區域。因此,該語句會清除可能存在於該區域的任何警告(並將 warning_count 重置為 0)。

  • 類別 = '02' (找不到)

    NOT FOUND 處理常式會捕獲訊號。對游標沒有影響。如果訊號在儲存函數中未處理,則語句會結束。

  • 類別 > '02' (例外狀況)

    SQLEXCEPTION 處理常式會捕獲訊號。如果訊號在儲存函數中未處理,則語句會結束。

  • 類別 = '40'

    被視為一般的例外狀況。