SQL 的 CHECK 约束详解
CHECK 约束(Check Constraint)是 SQL 中用于保证数据合法性和业务规则一致性的一种约束机制。它允许你为列或列组合定义一个布尔条件表达式,只有当表达式结果为
TRUE时,数据才能被插入或更新。
CHECK 约束是做什么的?
它的作用是:
- ✅ 限制列中允许存储的数据范围
- ✅ 防止不合法、不合理的数据写入数据库
- ✅ 将业务规则前移到数据库层,减少程序漏洞
例如:
- 年龄不能小于 18
- 金额必须大于 0
- 状态值只能是指定的几个枚举值
基本语法
列级 CHECK
1 | column_name data_type CHECK (condition) |
表级 CHECK(推荐,更清晰)
1 | CHECK (condition) |
只要 condition 结果不是 TRUE,插入或更新都会失败。
基础示例
1️⃣ 简单条件
员工年龄必须 ≥ 18:
1 | CREATE TABLE employees ( |
尝试插入非法数据会失败:
1 | INSERT INTO employees VALUES (1, 'Tom', 16); |
2️⃣ 多个列分别约束
1 | CREATE TABLE employees ( |
3️⃣ 组合条件(列之间的关系)
1 | CREATE TABLE employees ( |
这种写法更适合复杂规则,可读性也更好。
常用的表达式类型
1️⃣ 比较运算符
1 | = 等于 |
示例:
1 | CHECK (age >= 18) |
2️⃣ 逻辑运算符
1 | AND 并且 |
示例:
1 | CHECK (age BETWEEN 18 AND 60) |
3️⃣ 范围与集合
BETWEEN
1 | CHECK (age BETWEEN 18 AND 60) |
IN / NOT IN
1 | CHECK (status IN ('active', 'inactive', 'pending')) |
4️⃣ NULL 相关(非常重要)
⚠ CHECK 对 NULL 的行为容易被忽略
规则是:
如果 CHECK 表达式结果为 UNKNOWN(NULL),约束是通过的
例如:
1 | CHECK (age >= 18) |
当 age IS NULL 时:
- 表达式结果是
NULL - 不会触发 CHECK 错误
如果你不允许 NULL,必须显式写:
1 | age INT NOT NULL CHECK (age >= 18) |
或:
1 | CHECK (age IS NOT NULL AND age >= 18) |
5️⃣ 字符串匹配(LIKE / NOT LIKE)
1 | CHECK (email LIKE '%@%') |
| 符号 | 含义 |
|---|---|
% |
任意长度的任意字符(包括 0 个) |
_ |
恰好 1 个任意字符 |
部分数据库支持正则:
- MySQL:
REGEXP - PostgreSQL:
~
6️⃣ 算术运算
+加-减*乘/除%取模(部分数据库支持)()括号改变优先级
1 | CHECK (salary > 0) |
命名
给 CHECK 约束命名,方便排错和维护:
1 | CREATE TABLE employees ( |
报错信息会更清晰:
1 | violates check constraint "chk_employee_age" |
现有表添加 CHECK
已有表也可以后期添加:
1 | ALTER TABLE employees |
支持情况
| 数据库 | CHECK 是否生效 | 版本说明 | 关键限制 / 特点 |
|---|---|---|---|
| MySQL ≤ 5.7 | ❌ 不生效 | 语法存在但不会校验 | 仅解析,不执行 |
| MySQL ≥ 8.0.16 | ✅ 生效 | 真正支持 CHECK | 不允许子查询、非确定性函数 |
| PostgreSQL | ✅ 始终生效 | 所有版本 | 校验严格,功能最完整 |
| SQL Server | ✅ 生效 | 主流版本 | 语法稳定,限制较多 |
| Oracle | ✅ 生效 | 主流版本 | 企业级支持 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 码僧日记!
评论



