#### 13.1.20.6 检查约束

[](<>)

在 MySQL 8.0.16 之前，[`创建表`](create-table.html)仅允许以下有限版本的表`查看`约束语法，被解析和忽略：

```
CHECK (expr)
```

从 MySQL 8.0.16 开始，[`创建表`](create-table.html)允许表格和列的核心功能`查看`约束，适用于所有存储引擎。[`创建表`](create-table.html)允许以下`查看`约束语法，用于表约束和列约束：

```
[CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
```

可选的*`象征`*指定约束的名称。如果省略，MySQL 从表名生成一个名称，一个文字`_chk_`, 和一个序数 (1, 2, 3, ...)。约束名称的最大长度为 64 个字符。它们区分大小写，但不区分重音。

*`表达式`*将约束条件指定为必须计算为的布尔表达式`真的`要么`未知`（为了`空值`值）为表的每一行。如果条件评估为`错误的`，它失败并发生约束冲突。违反的影响取决于正在执行的语句，如本节后面所述。

可选的强制子句指示是否强制执行约束：

-   如果省略或指定为`强制执行`, 约束被创建和执行。

-   如果指定为`未强制执行`，约束已创建但未强制执行。

    一种`查看`约束被指定为表约束或列约束：

-   表约束不会出现在列定义中，并且可以引用任何表列。允许对表定义中稍后出现的列进行前向引用。

-   列约束出现在列定义中，并且只能引用该列。

    考虑这个表定义：


```
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 为任何`查看`没有指定的约束。要查看为前面的表定义生成的名称，请使用`显示创建表`：


```
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 中，每个约束类型都有自己的每个模式（数据库）的命名空间。所以，`查看`每个模式的约束名称必须是唯一的；同一架构中的两个表不能共享一个`查看`约束名称。（例外：A`暂时的`表隐藏了一个非`暂时的`同名的表，所以它可以有相同的`查看`约束名称也是如此。）

以表名开始生成的约束名有助于确保模式的唯一性，因为表名在模式中也必须是唯一的。

`查看`条件表达式必须遵守以下规则。如果表达式包含不允许的构造，则会发生错误。

-   允许使用非生成列和生成列，但具有`自动递增`其他表中的属性和列。

-   允许使用文字、确定性内置函数和运算符。如果给定表中的相同数据，则函数是确定性的，多次调用产生相同的结果，而与连接的用户无关。非确定性且不符合此定义的函数示例：[`CONNECTION_ID()`](information-functions.html#function_connection-id),[`当前用户（）`](information-functions.html#function_current-user),[`现在（）`](date-and-time-functions.html#function_now).

-   不允许存储函数和可加载函数。

-   不允许使用存储过程和函数参数。

-   不允许使用变量（系统变量、用户定义变量和存储的程序局部变量）。

-   不允许子查询。

    外键引用操作 (`在更新`,`删除时`) 禁止在使用的列上`查看`约束。同样地，`查看`在外键引用操作中使用的列上禁止约束。

`查看`约束被评估为[`插入`](insert.html),[`更新`](update.html),[`代替`](replace.html),[`加载数据`](load-data.html)， 和[`加载 XML`](load-xml.html)如果约束计算为`错误的`.如果发生错误，事务和非事务存储引擎对已应用更改的处理不同，并且还取决于严格 SQL 模式是否有效，如中所述[严格的 SQL 模式](sql-mode.html#sql-mode-strict).

`查看`约束被评估为[`插入忽略`](insert.html),[`更新忽略`](update.html),[`加载数据...忽略`](load-data.html)， 和[`加载 XML ...忽略`](load-xml.html)如果约束计算为`错误的`.跳过任何违规行的插入或更新。

如果约束表达式计算的数据类型与声明的列类型不同，则根据通常的 MySQL 类型转换规则对声明的类型进行隐式强制。看[第 12.3 节，“表达式求值中的类型转换”](type-conversion.html).如果类型转换失败或导致精度损失，则会发生错误。

笔记

约束表达式评估使用在评估时有效的 SQL 模式。如果表达式的任何组件依赖于 SQL 模式，则表的不同用途可能会出现不同的结果，除非在所有使用过程中 SQL 模式都相同。

这[`INFORMATION_SCHEMA.CHECK_CONSTRAINTS`](information-schema-check-constraints-table.html)表提供有关信息`查看`在表上定义的约束。看[第 26.3.5 节，“信息\_架构检查\_约束表”](information-schema-check-constraints-table.html).
