Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add description about check constraint #14227

Merged
merged 18 commits into from
Jun 26, 2023
Merged
61 changes: 50 additions & 11 deletions constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,59 @@ Query OK, 1 row affected (0.03 sec)

## `CHECK` 约束

TiDB 会解析并忽略 `CHECK` 约束。该行为与 MySQL 5.7 的相兼容
`CHECK` 约束是用来限制表中某个字段值必须满足特定条件的一种手段,TiDB 支持 `CHECK` 约束,语法与 MySQL 相同。添加 `CHECK` 约束后,TiDB 会在插入或者更新数据的时候,检查约束条件是否满足,如果不满足,那么会报错

示例如下:
`CHECK` 约束语法为:
```sql
[CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
```
其中`[]`中的内容表示可选项,`CONSTRAINT [symbol]` 表示 `CHECK` 约束的名称。`CHECK (expr)` 表示约束条件, 其中 `expr` 是一个布尔表达式,对于表的每一行,该表达式的计算结果必须为 `TRUE`、`FALSE` 或者 `UNKNOWN` (对于 `NULL` 值),如果对于某条数据表达式计算结果为 `FALSE`,则表示约束违反。`[NOT] ENFORCED` 表示是否执行约束,可以用来启用或者禁用 `CHECK` 约束。

### 添加约束
在 TiDB 中,可以在 `CREATE TABLE` 或者 `ALTER TABLE` 语句中添加 `CHECK` 约束,语法为:

在 `CREATE TABLE` 语句中添加约束:
```sql
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(60) NOT NULL,
UNIQUE KEY (username),
CONSTRAINT min_username_length CHECK (CHARACTER_LENGTH(username) >=4)
);
INSERT INTO users (username) VALUES ('a');
SELECT * FROM users;
CREATE TABLE t(a INT CHECK(a > 10) NOT ENFORCED, b INT, c INT, CONSTRAINT c1 CHECK (b > c));
```
在 `ALTER TABLE` 语句中添加约束:
```sql
ALTER TABLE t ADD CONSTRAINT CHECK (1 < c);
```
在创建或者启用 `CHECK` 约束时候,会对表中的存量数据进行校验,如果有违反约束的数据存在,那么添加 `CHECK` 约束会失败并且报错。

在添加 `CHECK` 约束的时,可以指定约束的名称,也可以不指定约束的名称,如果不指定约束的名称,那么系统会自动生成一个约束的名称,生成的约束名格式为 `<tableName>_chk_<1, 2, 3...>`。

如果需要查看表中 `CHECK` 约束的信息,你可以通过 `SHOW CREATE TABLE` 查看约束信息,例如:
```sql
mysql> show create table t;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t | CREATE TABLE `t` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
CONSTRAINT `c1` CHECK ((`b` > `c`)),
CONSTRAINT `t_chk_1` CHECK ((`a` > 10)) /*!80016 NOT ENFORCED */,
CONSTRAINT `t_chk_2` CHECK ((1 < `c`))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
```

### 删除约束
删除 `CHECK` 约束时使用名称 `symbol` 来删除指定的约束。语法为:
```sql
ALTER TABLE t DROP CONSTRAINT t_chk_1;
```

### 启用/禁用约束
在添加约束的时候,可以指定是否执行约束,如果指定了 `NOT ENFORCED`,那么在插入或者更新数据的时候,不会检查约束条件,如果不指定 `NOT ENFORCED` 或者指定 `ENFORCED`,那么在插入或者更新数据的时候,会检查约束条件。

除了在添加约束时候指定 `[NOT] ENFORCED`,你还可以在 `ALTER TABLE` 语句中启用或者禁用 `CHECK` 约束,语法为:
```sql
ALTER TABLE t ALTER CONSTRAINT c1 NOT ENFORCED;
```

## 唯一约束
Expand Down