在 MySQL 8.0.16 之前,CREATE
TABLE
只允许以下有限版本的表CHECK
约束语法,它被解析并被忽略:
CHECK (expr)
从 MySQL 8.0.16 开始,允许所有存储引擎
CREATE TABLE
使用表和列约束的核心功能
。对于表约束和列约束,允许使用以下约束语法:
CHECK
CREATE TABLE
CHECK
[CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
可选项symbol
指定约束的名称。如果省略,MySQL 会根据表名、文字_chk_
和序号(1、2、3、...)生成一个名称。约束名称的最大长度为 64 个字符。它们区分大小写,但不区分重音。
expr
将约束条件指定为布尔表达式,该表达式的计算结果必须
为表的每一行的TRUE
或UNKNOWN
(对于
值)。NULL
如果条件的计算结果为FALSE
,则它失败并发生约束冲突。违规的影响取决于正在执行的语句,如本节后面所述。
可选的 enforcement 子句指示约束是否被强制执行:
如果省略或指定为
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()
。不允许存储函数和可加载函数。
不允许使用存储过程和函数参数。
不允许使用变量(系统变量、用户定义的变量和存储的程序局部变量)。
不允许子查询。
约束中使用的列禁止使用
外键引用操作 ( ON UPDATE
,
)。同样,
在外键引用操作中使用的列也禁止约束。
ON DELETE
CHECK
CHECK
CHECK
对
INSERT
、
UPDATE
、
REPLACE
、
LOAD DATA
和
LOAD XML
语句评估约束,如果约束评估为 ,则会发生错误FALSE
。如果发生错误,事务和非事务存储引擎对已应用更改的处理会有所不同,并且还取决于严格 SQL 模式是否生效,如
严格 SQL 模式中所述。
CHECK
对
、
、 和
语句评估约束,如果约束评估为INSERT IGNORE
,
则会出现警告。跳过任何违规行的插入或更新。
UPDATE IGNORE
LOAD DATA ...
IGNORE
LOAD XML ...
IGNORE
FALSE
如果约束表达式的计算结果为不同于声明的列类型的数据类型,则根据通常的 MySQL 类型转换规则对声明的类型进行隐式强制转换。请参阅第 12.3 节,“表达式计算中的类型转换”。如果类型转换失败或导致精度损失,则会发生错误。
约束表达式求值使用求值时有效的 SQL 模式。如果表达式的任何部分依赖于 SQL 模式,则表的不同使用可能会产生不同的结果,除非 SQL 模式在所有使用过程中都相同。
该
INFORMATION_SCHEMA.CHECK_CONSTRAINTS
表提供有关CHECK
在表上定义的约束的信息。请参阅
第 26.3.5 节,“INFORMATION_SCHEMA CHECK_CONSTRAINTS 表”。