MySQL【表的约束上】

【MySQL 笔记】表的约束(上)—— 基础约束详解

表的约束(Constraints) 是数据库设计中最核心的部分之一,它从数据库层面强制规定数据的合法性、一致性和完整性。

MySQL 主要支持以下几种约束(InnoDB 引擎下最完整):

约束类型英文关键词作用是否允许 NULL是否允许重复每表可有几个级别(列级/表级)是否自动创建索引MySQL 版本特性
非空约束NOT NULL字段值不能为空列级全版本
默认值约束DEFAULT未指定值时自动填充列级全版本(8.0+ 支持函数如 NOW())
唯一约束UNIQUE [KEY]字段值全局唯一(除 NULL 外)是(多 NULL)列级 / 表级是(唯一索引)全版本
主键约束PRIMARY KEY唯一 + 非空 + 表唯一标识1列级 / 表级是(聚集索引)全版本
自增属性AUTO_INCREMENT自动递增(通常配合主键)1(每表)列级全版本
检查约束CHECK自定义表达式检查列级 / 表级8.0.16+ 真正强制执行
外键约束FOREIGN KEY参照完整性(关联其他表主键/唯一键)是(视情况)表级是(普通索引)全版本(InnoDB)

说明

  • 主键 = NOT NULL + UNIQUE + 表唯一
  • 唯一键 ≠ 主键(唯一键允许 NULL,主键不允许)
  • CHECK 在 MySQL 8.0.16 之前只是语法糖(不强制执行),8.0.16+ 才真正生效

二、创建表时添加约束的两种写法

  1. 列级约束(直接写在列定义后面)
  2. 表级约束(写在所有列后面,可起约束名)
CREATE TABLE users (
    id          INT AUTO_INCREMENT,
    username    VARCHAR(50) NOT NULL,
    email       VARCHAR(100) UNIQUE,
    phone       VARCHAR(20) DEFAULT '未填写',
    age         TINYINT UNSIGNED CHECK (age >= 0 AND age <= 150),
    status      TINYINT DEFAULT 1,

    -- 表级约束示例
    CONSTRAINT pk_users PRIMARY KEY (id),
    CONSTRAINT uk_users_email UNIQUE (email),          -- 可重复定义,但没必要
    CONSTRAINT chk_users_status CHECK (status IN (0,1,2))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

三、每种约束详细示例 & 常见写法

1. 非空约束(NOT NULL)

username VARCHAR(50) NOT NULL COMMENT '用户名',
  • 插入/更新时必须提供值,否则报错:Field 'username' doesn't have a default value

2. 默认值(DEFAULT)

-- 常量默认值
status TINYINT DEFAULT 1,

-- MySQL 8.0+ 支持表达式/函数(推荐)
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

3. 唯一约束(UNIQUE)

-- 列级
email VARCHAR(100) UNIQUE,

-- 表级(复合唯一)
CONSTRAINT uk_user_phone UNIQUE (phone, country_code),
  • 允许多个 NULL(NULL 不算重复)
  • 自动创建唯一索引

4. 主键约束(PRIMARY KEY)

-- 单列主键(最常见)
id BIGINT AUTO_INCREMENT PRIMARY KEY,

-- 复合主键(表级)
PRIMARY KEY (user_id, order_id),
  • 自动创建聚集索引(InnoDB)
  • 每表只能有一个主键

5. 自增(AUTO_INCREMENT)

id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  • 必须是整数类型 + 主键(或唯一键 + NOT NULL)
  • 起始值默认 1,可修改:ALTER TABLE t AUTO_INCREMENT = 1000;

6. 检查约束(CHECK)—— 8.0.16+

-- 列级
score TINYINT CHECK (score BETWEEN 0 AND 100),

-- 表级(多列关联)
CONSTRAINT chk_salary CHECK (salary > bonus),
  • 插入/更新时不满足条件会报错

7. 外键约束(FOREIGN KEY)—— 下期重点

-- 简单写法
user_id BIGINT,
FOREIGN KEY (user_id) REFERENCES users(id),

-- 带级联行为(推荐生产使用)
FOREIGN KEY (user_id) REFERENCES users(id)
    ON DELETE CASCADE          -- 主表删,从表也删
    ON UPDATE CASCADE,         -- 主表改,从表跟着改

常见级联选项:

  • CASCADE:级联
  • SET NULL:置空
  • RESTRICT / NO ACTION:禁止(默认)
  • SET DEFAULT:设默认值

四、约束相关常用操作

-- 查看表约束
SHOW CREATE TABLE users\G

-- 查看外键
SELECT * FROM information_schema.table_constraints 
WHERE table_name = 'orders';

-- 删除约束(需知道约束名)
ALTER TABLE users DROP FOREIGN KEY fk_orders_user;
ALTER TABLE users DROP PRIMARY KEY;
ALTER TABLE users DROP INDEX uk_email;

五、约束设计建议(2026 年生产经验)

  1. 几乎所有表都应该有主键(推荐自增或雪花ID)
  2. 业务唯一字段用 UNIQUE(如手机号、邮箱、订单号)
  3. 重要字段加 NOT NULL + DEFAULT
  4. 外键谨慎使用(性能开销大,小中型项目可考虑逻辑外键)
  5. CHECK 约束多用在 8.0+ 项目(年龄、状态枚举等)
  6. 约束名要规范pk_表名uk_表名_字段fk_从表_主表chk_表名_条件

下一期预告:表的约束(下)—— 外键详解 + 级联行为 + 约束 vs 索引区别 + 生产中常见坑

有哪种约束在项目里踩过坑,或者想看具体的外键级联演示,欢迎留言~
祝大家建表时约束加得又全又稳!🛡️

文章已创建 5186

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部