MySQL:数据库约束

一、约束的基本概念

1. 什么是约束

约束是数据库为了保证数据的完整性、准确性、有效性,对表数据添加的强制性规则。

  • 作用:减少数据冗余、避免无效数据、维护数据一致性
  • 分类:主键约束、唯一约束、非空约束、默认约束、外键约束

二、五类约束详解(附 SQL 示例)

(一)主键约束(PRIMARY KEY)

核心作用

  • 唯一标识表中的每一行数据,不允许重复、不允许为空
  • 一张表只能有一个主键 ,通常用 id 字段作为主键
  1. 基础使用示例

    -- 创建表时指定主键
    CREATE TABLE student (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    age INT,
    email VARCHAR(255)
    );

    -- 错误示例:插入重复主键(会报错)
    INSERT INTO student(id, name, age, email)
    VALUES (1, '张三', 18, '1443005893@qq.com');
    INSERT INTO student(id, name, age, email)
    VALUES (1, '李四', 20, '1443005893@qq.com');
    -- 报错:Duplicate entry '1' for key 'PRIMARY'

  2. 自增主键(AUTO_INCREMENT)

为了避免手动维护主键重复,MySQL 提供了自增特性,让数据库自动维护主键值:

复制代码
-- 创建自增主键表
CREATE TABLE student (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255),
    age INT,
    email VARCHAR(255)
);

-- 插入数据时无需指定 id,数据库自动生成
INSERT INTO student(name, age, email) 
VALUES ('张三', 18, '1443005893@qq.com');
INSERT INTO student(name, age, email) 
VALUES ('李四', 20, '1443005893@qq.com');
  1. AUTO_INCREMENT 特点

  2. 仅整数类型字段可设置自增

  3. 仅主键字段可设置自增

  4. 自增字段插入数据时可不赋值

  5. 初始值默认从 1 开始,步长为 1

  6. 自增字段一旦被使用过,后续不会再出现(即使数据被删除)


(二)唯一约束(UNIQUE)

核心作用

  • 保证列中数据不允许重复 ,但允许为空
  • 一张表中可以创建多个唯一约束(与主键的核心区别)
  • 注意:VARCHAR(255) 长度的字段,MySQL 无法设置唯一约束(索引长度限制)

使用示例

复制代码
CREATE TABLE student (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255),
    age INT,
    email VARCHAR(255) UNIQUE -- 邮箱不允许重复
);

-- 第一次插入正常
INSERT INTO student(name, age, email) 
VALUES ('张三', 18, '1443005893@qq.com');

-- 第二次插入重复邮箱,报错
INSERT INTO student(name, age, email) 
VALUES ('lisi', 20, '1443005893@qq.com');
-- 报错:Duplicate entry '1443005893@qq.com' for key 'email'

(三)非空约束(NOT NULL)

核心作用

  • 强制列中数据不允许为空,必须填写有效数据
  • 常用于必填字段,如用户名、手机号、密码等

使用示例

复制代码
CREATE TABLE student (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL, -- 姓名不允许为空
    age INT,
    email VARCHAR(255)
);

-- 错误示例:插入空姓名(会报错)
INSERT INTO student(name, age, email) 
VALUES (NULL, 18, '1443005893@qq.com');
-- 报错:Column 'name' cannot be null

(四)默认约束(DEFAULT)

核心作用

  • 为列设置默认值,当插入数据时不指定该列的值,会自动填充默认值
  • 常用于性别、状态、创建时间等字段

使用示例

复制代码
CREATE TABLE student (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    age INT DEFAULT 18, -- 年龄默认 18
    gender CHAR(1) DEFAULT '男' -- 性别默认男
);

-- 插入数据时不指定 age 和 gender,自动使用默认值
INSERT INTO student(name) VALUES ('张三');
-- 查询结果:age=18, gender='男'

(五)外键约束(FOREIGN KEY)

核心作用

  • 建立两张表之间的关联关系,保证数据的一致性、完整性
  • 用于一对多、多对多关系中,实现表间联动
  1. 基础使用示例

    -- 主表:部门表(父表)
    CREATE TABLE dept (
    dept_id INT PRIMARY KEY AUTO_INCREMENT,
    dept_name VARCHAR(50)
    );

    -- 从表:员工表(子表),通过外键关联部门表
    CREATE TABLE emp (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(50),
    dept_id INT,
    FOREIGN KEY (dept_id) REFERENCES dept(dept_id)
    );

  2. 外键字段配置项

配置项 说明
外键名(name) 可省略,系统自动生成
字段(field) 子表中用于关联的字段
参考数据库 外键关联的数据库
引用表(reference table) 关联的主表
外栏位名(outside field) 主表中被关联的字段
  1. 删除 / 更新时的联动规则
规则 作用
CASCADE 父表更新 / 删除记录时,子表对应记录同步更新 / 删除
SET NULL 父表更新 / 删除记录时,子表对应字段设为 NULL(子表字段需允许为空)
NO ACTION / RESTRICT 子表有匹配记录时,禁止父表更新 / 删除操作
  1. 注意事项

  2. 添加外键时,引擎必须为 InnoDB

  3. 外键字段必须与主表字段数据类型一致

  4. 主表字段必须是主键或唯一约束字段

  5. 外键会影响插入、更新、删除性能,数据仓库场景通常不建议使用


三、约束的综合应用示例(学生表完整设计)

复制代码
CREATE TABLE student (
    -- 主键约束 + 自增
    id INT PRIMARY KEY AUTO_INCREMENT,
    -- 非空约束
    name VARCHAR(255) NOT NULL,
    -- 默认约束
    age INT DEFAULT 18,
    -- 唯一约束
    email VARCHAR(255) UNIQUE,
    -- 外键约束(关联班级表)
    class_id INT,
    FOREIGN KEY (class_id) REFERENCES class(class_id)
);

四、约束设计最佳实践

  1. 主键设计 :优先使用自增 INT 类型,避免使用业务字段作为主键(如学号、手机号)
  2. 唯一约束:手机号、邮箱等字段建议添加唯一约束,避免重复数据
  3. 非空约束 :必填字段必须设置 NOT NULL,避免逻辑错误
  4. 外键使用:业务系统中可使用外键保证一致性;数据仓库、大数据场景建议通过应用层控制数据一致性,避免性能损耗
  5. 默认值设计:合理使用默认值,减少插入语句的冗余字段

五、约束常见报错与解决

报错场景 错误原因 解决方法
Duplicate entry 主键 / 唯一约束重复 检查插入数据是否重复,或使用自增主键
Column cannot be null 非空约束字段插入空值 为非空字段提供有效数据
Foreign key constraint fails 外键关联数据不存在 先插入主表数据,再插入子表
相关推荐
过期动态1 小时前
【RabbitMQ基础篇】RabbitMQ从入门到实战
java·jvm·数据库·分布式·spring·rabbitmq·intellij-idea
刘~浪地球1 小时前
MongoDB聚合管道进阶:数据处理与统计分析
数据库·mongodb
瀚高PG实验室1 小时前
debezium在LANG=zh_CN.UTF-8下,无法解析timestamp类型的列值为BC的字段
服务器·数据库·postgresql·瀚高数据库
刘~浪地球1 小时前
MongoDB索引优化实战:让查询飞起来
数据库·mongodb
AstartesEternal1 小时前
REDIS下载及安装教程
数据库·redis·缓存
Allen_LVyingbo2 小时前
面向医疗群体智能的协同诊疗与群体决策支持系统(上)
数据结构·数据库·人工智能·git·python·动态规划
东南门吹雪2 小时前
Spring事务传播机制深度解析
java·数据库·spring
不甘先生2 小时前
PostgreSQL 中的 JSONB 详解:从入门到实战
数据库·postgresql