MySQL 六大基础约束详解:NOT NULL/DEFAULT/UNIQUE/ 主键 / 外键 / CHECK

📚 目录

  • [1. 什么是数据库约束?](#1. 什么是数据库约束?)
    • [1.1 数据库约束类型的介绍](#1.1 数据库约束类型的介绍)
  • [2. 数据库约束实操](#2. 数据库约束实操)
    • [2.1 字段级约束:not null / default / unique / check](#2.1 字段级约束:not null / default / unique / check)
    • [2.2 表级约束:primary key 主键](#2.2 表级约束:primary key 主键)
    • [2.3 关联约束:foreign key 外键](#2.3 关联约束:foreign key 外键)

前言:

  数据完整性是数据库设计的核心目标,MySQL 通过约束机制限制字段输入规范,规避空值、重复、非法数值、无效关联等脏数据。

  本文会分类讲解六大基础约束,区分字段级、表级、外键关联约束,附完整建表示例,从概念到实操一步步讲解,适合零基础同学系统学习,也可作为开发速查笔记。

1. 什么是数据库约束?

  想必大家都见过牵绳遛狗的场景:牵引绳就相当于一种约束,限制狗狗随意乱跑、避免伤人,规范它的活动范围。

**  数据库约束是用于保证数据完整性和一致性的一组规则,它强制数据必须遵守特定条件,否则数据库操作会被拒绝。**

1.1 数据库约束类型的介绍

  六大基础约束主要分为三部分:子段级,表级,外键关联约束

类型 说明
not null 非空约束 指定非空约束的列不能存储 null 值
default 默认约束 当没有给列赋值时使用的默认值
unique 唯一约束 指定唯一约束的列每行数据必须有唯一的值
primary key 主键约束 not null 和 unique 的结合,可以指定一个列或多个列,有助于防止数据重复和提高数据的查询性能
foreign key 外键约束 外键约束是一种关系约束,用于定义两个表之间的关联关系,可以确保数据的完整性和一致性
check 约束 用于限制列或数据在数据库表中的值,确保数据的准确性和可靠性

[🔙 返回目录](#🔙 返回目录)


2. 数据库约束实操

2.1 字段级约束:not null / default / unique / check

字段级约束not null:

  作用:限制某字段不能为空,插入/更新该字段必须传入有效值,不允许为null;

sql 复制代码
 create table if not exists test (
	id int not null,
	name varchar(20)
);

  我们可以使用desc来查看表结构:

sql 复制代码
desc test;

  我们可以看见: id列null位置的值为:NO ;此时就代表我们插入的元素不能为null,否则会报错;

sql 复制代码
insert into test(id,name) values (1,'张三');
insert into test (name) values('王五');
insert into test  values(null,'王五');

  结果:

  从执行结果可以看出,只有第一条 insert 语句成功执行。

字段级约束default:

**  作用:插入数据时若不给该字段传值,自动填充预设默认值;**

sql 复制代码
 create table if not exists test (
	id int,
	name varchar(20) default '匿名'
);

  表结构:

  也就是说,当我们没有指定当前列进行插入的时候,会自动帮我们插入默认值;

  例如:

sql 复制代码
-- 插入
insert into test(id) values (1);
-- 查询
select* from test;

  当我们没有指定列进行插入的时候,会采取默认值;

字段级约束 unique:

**  作用:当前字段所有行数据不能重复,允许存入多个 null。**

sql 复制代码
 create table if not exists test (
	id int unique,
	name varchar(20)
);
insert into test(id,name) values (1,'张三');
insert into test(id,name) values (2,'王五');

  具体表结构:

  此时插入的数据都能够成功进行插入,当我们再插入id为1的值的时候,就会报错:

sql 复制代码
insert into test(id,name) values (1,'李四');

字段级约束check:

**  作用:自定义字段取值范围,不符合条件的数据直接拦截。**

sql 复制代码
 create table if not exists test (
	id int 	check(id<10 and id > 5),
	name varchar(20)
);

  表结构:

  插入数据:

sql 复制代码
insert into test(id,name) values (6,'张三');
insert into test(id,name) values (7,'王五');
insert into test(id,name) values (8,'李四');

  此时插入:这三条数据都是符合要求的数据,当我们插入不符合要求的数据,就会报错:

sql 复制代码
insert into test(id,name) values (1,'李四');
insert into test(id,name) values (11,'李四');


[🔙 返回目录](#🔙 返回目录)


2.2 表级约束:primary key 主键

  主键约束等价于 not null + unique,一张表只能有一个主键,分为单字段主键复合多字段主键 ,同时主键会自动生成索引,大幅提升查询速度。

  方式1: 字段后面直接声明;

sql 复制代码
create table user(
    id int primary key comment '用户主键id',
    username varchar(20) not null
);

  方式2: 表末尾统一声明(支持复合主键)

sql 复制代码
 create table user_role(
    user_id int,
    role_id int,
    -- 复合主键,user_id + role_id 组合唯一
    primary key(user_id, role_id)
);

注意:

1. 主键字段不能为 null,整表唯一;
2. 一张表仅允许存在一组 primary key;
3. 推荐使用自增 int 类型作为业务主键。

自增主键:auto_increment

  当我们没有指定主键列进行插入数据的时候,数据库会自动根据表中最大值进行插入:

例如:

sql 复制代码
insert into user_role (username) values ('张三');

  此时我们可以知道:自增主键是从1开始的;

sql 复制代码
insert into user_role (username) values ('张三');
insert into user_role  values (100,'张三');
insert into user_role (username) values ('张三');

  结果:

  自增主键是在最大值的基础上进行相加1的;

  我们也可以进行修改自增主键增加的位置:

修改自增主键

  • 表必须是 auto_increment 自增主键;
  • 新起始值必须大于当前表已存在最大主键 id;
  • 若表内已有数据,不能设置比现有最大 id 更小的值。
    方法一:
sql 复制代码
alter table 表名 auto_increment = 目标起始值;

方法二:

sql 复制代码
truncate table 表名;

注意:

  1. truncate(清空所有数据,自增直接重置为 1)并且数据不可恢复

  2. 外键关联场景下,子表不能直接 truncate,需先解除外键 / 删除子表数据

  3. delete 删除数据不会重置自增

    方法三: 表内数据已存在,想把自增改小(只能删数据重建)

MySQL 不支持将自增起点修改为小于当前已存在最大主键的数值,若业务需要缩小自增起点,只能先删除对应 id 区间的数据,再执行 alter table 修改。
[🔙 返回目录](#🔙 返回目录)


2.3 关联约束:foreign key 外键

**  作用: 外键用来维护两张表的参照完整性,子表字段必须匹配主表主键,防止出现无关联的脏数据;仅 InnoDB 引擎支持外键,MyISAM 不生效**

sql 复制代码
 create table if not exists class (
  	class_id int primary key auto_increment,
	name varchar(20)
);

create table if not exists student (
    student_id int primary key auto_increment,
    name varchar(20) not null,
    class_id int,
    foreign key(class_id) references class(class_id)
);

核心规则:

  1. 插入学生数据时,class_id 必须是 class 表里已存在的班级编号,否则插入失败;
  2. 不能直接删除还有学生关联的班级数据,数据库会拦截删除操作;
  3. 外键字段 class_id 和关联主键 class_id 的数据类型必须完全一致;
  4. 进阶扩展:可追加 on update cascade、on delete cascade 实现级联更新 / 删除

例如:

  我们先向:class中添加几个数据:

sql 复制代码
insert into class(name) values
('一班'),
('二班'),
('三班');

  执行后 class_id 会自增生成 1、2、3。

sql 复制代码
insert into student(name, class_id) values
('张三', 1),
('李四', 1),
('王五', 2),
('赵六', 3);

  此时我们是能成功进行 插入的;

  当我们插入不在class中存在的数据时:数据库会报错;

sql 复制代码
insert into student(name, class_id) values('小明', 99);
  • 执行顺序强制要求:有外键关联时,先创建主表,后创建子表,如果先执行 student 表建表语句,此时class表不存在,MySQL 会直接创建失败,student 表不会生成,后续执行 insert 语句会报Unknown column 'class_id'字段不存在错误。
  • 字段类型匹配:外键字段class_id和关联主键class_id数据类型必须完全一致(本例均为 int)
  • 存储引擎限制:只有innodb引擎支持外键,myisam 引擎外键不会生效,无法校验关联数据。
  • 约束效果:插入、更新学生时,class_id必须是 class 表中已存在的主键值;无法直接删除存在关联学生的班级数据。

[🔙 返回目录](#🔙 返回目录)


相关推荐
Anokata2 小时前
MYSQL SQL 执行系列1
android·sql·mysql
JSON_L2 小时前
MongoDB文档关系详解
数据库·mongodb
卓怡学长2 小时前
w268基于springboot + vue 物流系统
java·数据库·vue.js·spring boot·spring·intellij-idea
REDcker2 小时前
Android 15 16KB 内存页适配详解
android·开发语言·python
Kapaseker2 小时前
Android 开放这扇门,正在被 Google 从里面反锁
android·kotlin
CodeStats2 小时前
《源纹天书》第一百四十一章至第一百四十五章:etcd升级、2PC的阻塞困境、3PC的超时突破、TCC的补偿之道、Saga的最终选择!
java·大数据·数据库·etcd·源纹天书
Java成神之路-3 小时前
彻底分清:垂直分库、水平分库、垂直分表、水平分表(附 Mycat 完整配置)
mysql
帅次3 小时前
Android 高级工程师面试:网络与数据层 近1年高频追问 18 题
android·网络·okhttp·面试·retrofit·gilde
.Cnn3 小时前
Redis基础day02
java·数据库·redis