在 MySQL 8.0.16 之前,CREATE TABLE 只允许以下有限功能版本的表 CHECK 约束语法,它被解析并忽略:从 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,则失败并违反了约束。违规的影响取决于所执行的语句,本节稍后将对此进行描述。● 如果省略或指定 ENFORCED,则创建并强制约束。● 如果指定为 NOT ENFORCED,则创建约束但不强制执行。● 表约束不出现在列定义中,可以引用任何表列。允许对表定义后面出现的列进行前向引用。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 约束名称。(例外:临时表隐藏了同名的非临时表,因此它也可以有相同的 CHECK 约束名称。)以表名为开头生成的约束名有助于确保模式惟一性,因为表名在模式中也必须是惟一的。CHECK 条件表达式必须遵守以下规则。如果表达式包含不允许的构造,则会发生错误。● 允许非生成列和生成列,但具有 AUTO_INCREMENT 属性的列和其他表中的列除外。● 允许使用字面量、确定性内置函数和操作符。对于表中相同的数据,多次调用确定性函数产生相同的结果,而不依赖于所连接的用户。结果不确定且未通过此定义的函数示例: CONNECTION_ID()、CURRENT_USER() 和 NOW()。● 不允许使用变量(系统变量、用户定义变量和存储程序局部变量)。在 CHECK 约束中使用的列上禁止外键引用操作(ON UPDATE, ON DELETE)。同样,在外键引用操作中使用的列上禁止 CHECK 约束。CHECK 约束将针对 INSERT、UPDATE、REPLACE、LOAD DATA 和 LOAD XML 语句进行评估,如果约束的评估结果为 FALSE,则会出现错误。如果发生错误,事务性和非事务性存储引擎对已经应用的更改的处理是不同的,还取决于是否处于严格SQL模式中。CHECK 约束将针对 INSERT IGNORE,UPDATE IGNORE,LOAD DATA ... IGNORE 和 LOAD XML ... IGNORE 语句进行评估 ,如果约束的评估结果为 FALSE,则会出现警告。将跳过任何违规行的插入或更新。如果约束表达式要计算的数据类型与声明的列类型不同,则会根据通常的 MySQL 类型转换规则对声明的列类型进行隐式强制转换。如果类型转换失败或导致精度丢失,则会发生错误。约束表达式计算在计算时使用有效的SQL模式。如果表达式的任何组件依赖于SQL模式,则表的使用可能产生不同的结果,除非SQL模式在所有使用期间是相同的。https://dev.mysql.com/doc/refman/8.0/en/create-table-check-constraints.html