CREATE TABLE
允許所有儲存引擎的核心表格和欄位 CHECK
約束功能。CREATE TABLE
允許以下 CHECK
約束語法,適用於表格約束和欄位約束。
[CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
可選的 symbol
指定約束的名稱。如果省略,MySQL 會從表格名稱、文字 _chk_
和序號 (1, 2, 3, ...) 產生名稱。約束名稱的最大長度為 64 個字元。它們區分大小寫,但不區分重音符號。
expr
將約束條件指定為布林運算式,該運算式對於表格的每一列必須評估為 TRUE
或 UNKNOWN
(針對 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 UPDATE
、ON DELETE
)。同樣,禁止在用於外鍵參照動作的欄位上使用 CHECK
約束。
對於 INSERT
、UPDATE
、REPLACE
、LOAD DATA
和 LOAD XML
語句會評估 CHECK
約束,如果約束評估為 FALSE
,則會發生錯誤。如果發生錯誤,對於交易式和非交易式儲存引擎,以及是否啟用嚴格 SQL 模式,已套用變更的處理方式會有所不同,如嚴格 SQL 模式中所述。
對於 INSERT IGNORE
、UPDATE IGNORE
、LOAD DATA ... IGNORE
和 LOAD XML ... IGNORE
語句會評估 CHECK
約束,如果約束評估為 FALSE
,則會發生警告。將跳過任何違規列的插入或更新。
如果約束運算式評估為與宣告的欄位類型不同的資料類型,則會根據常用的 MySQL 類型轉換規則,隱式強制轉換為宣告的類型。請參閱 第 14.3 節「運算式評估中的類型轉換」。如果類型轉換失敗或導致精確度損失,則會發生錯誤。
約束運算式評估使用評估時生效的 SQL 模式。如果運算式的任何元件取決於 SQL 模式,則除非所有使用期間的 SQL 模式相同,否則表格的不同使用可能會產生不同的結果。
資訊綱要 CHECK_CONSTRAINTS
表格提供表格上定義的 CHECK
約束的相關資訊。請參閱第 28.3.5 節「INFORMATION_SCHEMA CHECK_CONSTRAINTS 表格」。