文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  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 擴充功能 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_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'

    視為一般的例外狀況。