Mysql之表的约束详解

非空约束 not null

sql 复制代码
create table myclass(
    class_name varchar(20) not null,
    class_room varchar(20) not null
);

补充几个新手容易懵的点:

  • not null 只表示"不能是 NULL",空字符串 '' 不算 NULL,所以 '' 可以插进去。
  • 如果这一列既 not null 又没有 default,插入时不给它值,MySQL 会直接翻脸报错。
  • 建表后也能加:
sql 复制代码
alter table myclass modify class_name varchar(20) not null;

default 约束

你原代码里 unsinged 拼错了,是 unsigned。修正后:

sql 复制代码
create table tt10(
    name varchar(20) not null,
    age tinyint unsigned default 18,
    gender char(1) default '男'
);
sql 复制代码
create table t11(
    name varchar(20) not null,
    age tinyint default 18,
    gender char(1) not null default '男'
);

补充:

  • insert into t11(name) values('张三'); 时,age 用 18,gender'男'
  • 如果 insert into t11() values();,会失败,因为 namenot null 又没默认值。
  • defaultnot null 不是敌人,是搭档:一个管"不能不填",一个管"不填时填啥"。

列描述 comment

sql 复制代码
create table t12(
    name varchar(20) not null comment '这个是用户的用户名',
    age tinyint unsigned default 18 comment '这个是用户年龄',
    gender char(1) default '男' comment '这个是用户性别'
);

补充:

  • comment 不是约束,删了也不影响数据,它更像是给管理员和未来的自己看的备注。
  • 除了 show create table t12;,还可以:
sql 复制代码
show full columns from t12;

zerofill 约束

sql 复制代码
create table test_zerofill (
    id int(6) zerofill primary key,
    num tinyint(4) zerofill
);

补充:

  • int(6)6 不是存储上限,只是显示宽度,而且只有配 zerofill 才明显有用。
  • 插入 1,可能显示成 000001
  • zerofill 会隐式变成 unsigned,所以不能存负数。
  • MySQL 8.0.17 后官方已经不推荐 zerofill,新项目别用,但面试题里偶尔还会冒出来吓人。

主键约束

sql 复制代码
create table student (
    id int primary key,
    name varchar(20)
);

一句话:primary key = unique + not null

补充:

  • 一张表最多一个主键,但主键可以是多个字段一起组成,叫联合主键。
  • InnoDB 里,主键就是聚簇索引。
  • 如果没有主键,InnoDB 会找第一个非空唯一索引当主键;找不到就偷偷生成一个隐藏主键。
  • 业务字段如手机号、身份证号,尽量别做主键,又长又可能变,推荐自增 int

建表后加主键:

sql 复制代码
alter table student add primary key(id);

删除主键时注意:如果主键带 auto_increment,要先去掉自增,不然可能报错。

sql 复制代码
alter table student modify id int;
alter table student drop primary key;

自增主键常用写法:

sql 复制代码
create table student (
    id int primary key auto_increment,
    name varchar(20)
);

补充:自增不保证连续,删掉几行后不会自动回填。可以指定起始值:

sql 复制代码
alter table student auto_increment = 100;

联合主键:

sql 复制代码
create table score (
    student_id int,
    course_id int,
    score int,
    primary key (student_id, course_id)
);

唯一键 unique

sql 复制代码
-- 列级定义
create table user(
    id int primary key auto_increment,
    email varchar(50) unique,
    phone varchar(20)
);

-- 表级定义,支持复合唯一键
create table user(
    id int primary key auto_increment,
    username varchar(30),
    phone varchar(20),
    constraint uk_name_phone unique (username, phone)
);

-- 已存在的表加唯一约束
alter table user add constraint uk_email unique(email);

-- 删除唯一约束,本质是删对应索引
alter table user drop index uk_email;

补充:

  • 唯一键可以有多个。
  • 唯一键允许 NULL,而且多个 NULL 不冲突,因为 NULL 不等于 NULL。
  • 底层就是唯一索引,所以 show index from user; 能看到。
特性 主键 PRIMARY KEY 唯一键 UNIQUE
数量 一张表只能 1 个 可以多个
NULL 不允许 允许,可多条 NULL
索引 InnoDB 聚簇索引 普通唯一二级索引
作用 唯一标识一行 保证业务字段不重复

外键 foreign key

外键就是两张表之间的"绳子":子表引用主表的主键或唯一键。

sql 复制代码
create table department(
    dept_id int primary key auto_increment,
    dept_name varchar(30) not null
);

create table employee(
    emp_id int primary key auto_increment,
    emp_name varchar(30) not null,
    dept_id int,
    constraint fk_emp_dept foreign key(dept_id) references department(dept_id)
);

规则补充:

  1. 被引用的列必须是主键或唯一键。
  2. 类型要匹配,intintvarchar 长度尽量一致。
  3. MySQL 里只有 InnoDB 支持外键,MyISAM 不支持。
  4. 插入:先插主表,再插子表。
  5. 删除:先删子表,再删主表。
  6. 可以加级联操作:
sql 复制代码
constraint fk_emp_dept foreign key(dept_id) references department(dept_id)
on delete cascade
on update cascade

意思就是:主表删,子表跟着删;主表改,子表跟着改。默认是 restrict,不让乱删。

删除外键:

sql 复制代码
alter table employee drop foreign key fk_emp_dept;

忘名字就:

sql 复制代码
show create table employee;

实际开发小提示:互联网项目经常不建物理外键,靠代码层保证,因为外键有性能和管理开销。学习阶段先把原理搞懂,面试能说清楚就行。

补一个:check 约束

MySQL 8.0.16 之后开始真正支持:

sql 复制代码
create table person(
    age int check (age >= 0 and age <= 150)
);

8.0.16 之前写是能写,但会被忽略,属于"写了白写"。

最后一句总结

数据库约束就像家规:

  • not null:这里不许空。
  • default:你不填,我给你兜底。
  • comment:给管理员看的备注。
  • zerofill:显示补零,老版本玩具,新项目别碰。
  • primary key:身份证,唯一且非空。
  • unique:业务唯一,可多个,可 NULL。
  • foreign key:两张表的绳子,先主后子。
  • check:条件必须满足。

刚开始记不住很正常,写多了就会形成条件反射:哦,这里不能空;哦,这里不能重复;哦,删主表前得先看子表。一年正是踩坑长记性的黄金期,稳住。

相关推荐
Java内核笔记1 小时前
Spring Boot 4 与 Spring AI 2.0 深度集成:ChatClient、Advisor 链与 MCP(源码级实战)
java·后端
吃饱了得干活1 小时前
一个订单的奇幻漂流:RabbitMQ 五大难题实战
spring boot·后端·rabbitmq
她的男孩1 小时前
账号锁定配了"错 4 次锁 30 分钟",我连错 100 次一次没锁上:扒完 4091 行认证源码,找到 5 个坑
java·后端·架构
Methy1 小时前
一次线上死锁排查:std::list::size () 居然是 O (n)?
c++·后端
MacroZheng1 小时前
Redis官方发布高颜值可视化工具,功能更是强的离谱!
java·redis·后端
回家路上绕了弯1 小时前
为什么 AI 写代码时,总喜欢“防御性编程”?
后端
灯澜忆梦2 小时前
【Redis中间件】#4 | 进阶数据类型语法
redis·后端
广州山泉婚姻2 小时前
前后端分离的核心优势
前端·后端
IT_陈寒2 小时前
Vue的响应式让我加班到凌晨,问题竟出在这个不起眼的地方
前端·人工智能·后端