Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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 中,每种约束类型在每个 schema(数据库)都有自己的命名空间。因此,CHECK 约束名称必须是唯一的 per schema;同一个 schema 中不能共享 CHECK 约束名称。(例外:临时表隐藏非临时表相同名称,可以拥有相同 CHECK 约束名。)

以表名开头生成约束名称有助于确保架构的唯一性,因为架构中的表名也必须是唯一的。

CHECK 条件表达式必须遵守以下规则。如果一个表达式包含不允许的结构,会出现错误。

  • 非生成列和生成列都是允许的,除了具有AUTO_INCREMENT属性的列和其他表中的列。

  • 字面量、确定性内置函数和操作符是允许的。一个函数是确定性的,如果给定同样的数据在表中,多次调用产生相同的结果,不管连接的用户是什么。例如,CONNECTION_ID()CURRENT_USER()NOW() 等函数都不是确定性的。

  • 存储函数和可加载函数是不允许的。

  • 存储程序和函数参数是不允许的。

  • 变量(系统变量、用户定义变量和存储程序局部变量)也不允许。

  • 子查询不允许。

外键引用操作(ON UPDATEON DELETE)在CHECK约束列上是禁止的。同样,CHECK约束也不能在外键引用操作列上。

CHECK 约束对INSERTUPDATEREPLACELOAD DATALOAD XML语句进行评估,如果约束评估为FALSE,则发生错误。如果发生错误,事务性存储引擎和非事务性存储引擎的更改处理方式不同,同时也取决于是否启用严格SQL模式,详见严格 SQL 模式

CHECK 约束对INSERT IGNOREUPDATE IGNORELOAD DATA ... IGNORELOAD XML ... IGNORE语句进行评估,如果约束评估为FALSE,则发出警告,并且跳过任何违反行的插入或更新。

如果约束表达式计算结果的数据类型与声明的列类型不同,会根据 MySQL 通用转换规则隐式强制转换到声明的类型。见第14.3节,“表达式求值中的类型转换”。如果类型转换失败或导致精度损失,会出现错误。

Note

约束表达式计算使用评估时间的 SQL 模式。如果表达式中的任何组件依赖于 SQL 模式,可能在不同的使用场景下产生不同结果,除非在所有使用场景中都保持相同的 SQL 模式。

信息架构CHECK_CONSTRAINTS表提供了对表定义的CHECK约束信息。见第28.3.5节,“INFORMATION_SCHEMA CHECK_CONSTRAINTS 表”.