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 模式都相同,否则不同的表使用可能会产生不同的结果。
Information Schema CHECK_CONSTRAINTS
表提供了有关在表上定义的 CHECK
约束的信息。请参见 第 28.3.5 节“INFORMATION_SCHEMA CHECK_CONSTRAINTS 表”.