文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 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 參考手冊  /  ...  /  CHECK 限制條件

15.1.20.6 CHECK 限制條件

CREATE TABLE 允許所有儲存引擎的核心表格和欄位 CHECK 約束功能。CREATE TABLE 允許以下 CHECK 約束語法,適用於表格約束和欄位約束。

[CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]

可選的 symbol 指定約束的名稱。如果省略,MySQL 會從表格名稱、文字 _chk_ 和序號 (1, 2, 3, ...) 產生名稱。約束名稱的最大長度為 64 個字元。它們區分大小寫,但不區分重音符號。

expr 將約束條件指定為布林運算式,該運算式對於表格的每一列必須評估為 TRUEUNKNOWN(針對 NULL 值)。如果條件評估為 FALSE,則會失敗並發生約束違規。違規的影響取決於執行的語句,如下一節所述。

可選的強制條款指出是否強制執行約束。

  • 如果省略或指定為 ENFORCED,則會建立並強制執行約束。

  • 如果指定為 NOT ENFORCED,則會建立約束但不強制執行。

CHECK 約束可以指定為表格約束或欄位約束。

  • 表格約束不會出現在欄位定義中,並且可以引用任何表格欄位或多個欄位。允許向前引用表格定義中稍後出現的欄位。

  • 欄位約束出現在欄位定義中,並且只能引用該欄位。

考慮以下表格定義:

CREATE TABLE t1
(
  CHECK (c1 <> c2),
  c1 INT CHECK (c1 > 10),
  c2 INT CONSTRAINT c2_positive CHECK (c2 > 0),
  c3 INT CHECK (c3 < 100),
  CONSTRAINT c1_nonzero CHECK (c1 <> 0),
  CHECK (c1 > c3)
);

定義包括表格約束和欄位約束,採用命名和未命名的格式。

  • 第一個約束是表格約束:它出現在任何欄位定義之外,因此可以(而且確實)引用多個表格欄位。此約束包含對尚未定義欄位的向前引用。未指定約束名稱,因此 MySQL 會產生名稱。

  • 接下來的三個約束是欄位約束:每一個都出現在欄位定義中,因此只能引用正在定義的欄位。其中一個約束已明確命名。MySQL 會為其他兩個約束產生名稱。

  • 最後兩個約束是表格約束。其中一個約束已明確命名。MySQL 會為另一個約束產生名稱。

如前所述,MySQL 會為任何未指定名稱的 CHECK 約束產生名稱。若要查看為上述表格定義產生的名稱,請使用 SHOW CREATE TABLE

mysql> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `c1` int(11) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  `c3` int(11) DEFAULT NULL,
  CONSTRAINT `c1_nonzero` CHECK ((`c1` <> 0)),
  CONSTRAINT `c2_positive` CHECK ((`c2` > 0)),
  CONSTRAINT `t1_chk_1` CHECK ((`c1` <> `c2`)),
  CONSTRAINT `t1_chk_2` CHECK ((`c1` > 10)),
  CONSTRAINT `t1_chk_3` CHECK ((`c3` < 100)),
  CONSTRAINT `t1_chk_4` CHECK ((`c1` > `c3`))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

SQL 標準規定,所有類型的約束(主鍵、唯一索引、外鍵、檢查)都屬於同一個命名空間。在 MySQL 中,每種類型的約束在每個綱要(資料庫)中都有自己的命名空間。因此,CHECK 約束名稱在每個綱要中必須是唯一的;同一個綱要中的任何兩個表格都不能共用 CHECK 約束名稱。(例外情況:TEMPORARY 表格會隱藏同名的非 TEMPORARY 表格,因此它也可以具有相同的 CHECK 約束名稱。)

以表格名稱開頭產生約束名稱有助於確保綱要的唯一性,因為表格名稱在綱要中也必須是唯一的。

CHECK 條件運算式必須遵守以下規則。如果運算式包含不允許的結構,則會發生錯誤。

  • 允許使用非產生欄位和產生欄位,但具有 AUTO_INCREMENT 屬性的欄位和在其他表格中的欄位除外。

  • 允許使用常值、決定性內建函數和運算子。如果給定表格中的相同資料,多次調用函數會產生相同的結果,而與連線的使用者無關,則該函數是決定性的。非決定性函數且不符合此定義的範例:CONNECTION_ID()CURRENT_USER()NOW()

  • 不允許使用儲存函數和可載入函數。

  • 不允許使用儲存程序和函數參數。

  • 不允許使用變數(系統變數、使用者定義變數和儲存程式本機變數)。

  • 不允許使用子查詢。

禁止在 CHECK 約束中使用的欄位上使用外鍵參照動作 (ON UPDATEON DELETE)。同樣,禁止在用於外鍵參照動作的欄位上使用 CHECK 約束。

對於 INSERTUPDATEREPLACELOAD DATALOAD XML 語句會評估 CHECK 約束,如果約束評估為 FALSE,則會發生錯誤。如果發生錯誤,對於交易式和非交易式儲存引擎,以及是否啟用嚴格 SQL 模式,已套用變更的處理方式會有所不同,如嚴格 SQL 模式中所述。

對於 INSERT IGNOREUPDATE IGNORELOAD DATA ... IGNORELOAD XML ... IGNORE 語句會評估 CHECK 約束,如果約束評估為 FALSE,則會發生警告。將跳過任何違規列的插入或更新。

如果約束運算式評估為與宣告的欄位類型不同的資料類型,則會根據常用的 MySQL 類型轉換規則,隱式強制轉換為宣告的類型。請參閱 第 14.3 節「運算式評估中的類型轉換」。如果類型轉換失敗或導致精確度損失,則會發生錯誤。

注意

約束運算式評估使用評估時生效的 SQL 模式。如果運算式的任何元件取決於 SQL 模式,則除非所有使用期間的 SQL 模式相同,否則表格的不同使用可能會產生不同的結果。

資訊綱要 CHECK_CONSTRAINTS 表格提供表格上定義的 CHECK 約束的相關資訊。請參閱第 28.3.5 節「INFORMATION_SCHEMA CHECK_CONSTRAINTS 表格」