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 约束

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:条件必须满足。

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

相关推荐
_院长大人_3 天前
使用 GitHub 作为图床:PicGo + Typora 自动上传完整教程
github·typora·picgo·图床
水巷石子12 天前
目前最新版本PicGo上传图片到gitee仓库具体配置
gitee·上传·typora·picgo·图片
小徐敲java22 天前
Typora破解
typora
吴声子夜歌1 个月前
Typora——段落排版
typora·markdown
VIP_CQCRE1 个月前
用 Ace Data Cloud 自动把技术内容发布到 CSDN:AI 写作、图片托管、数据回看一站搞定
ai·api·csdn·内容营销·acedatacloud
VIP_CQCRE1 个月前
用 Ace Data Cloud 自动化运营 CSDN:AI 写作、配图、发布与数据复盘
ai·自动化·api·csdn·acedatacloud
VIP_CQCRE1 个月前
用 Ace Data Cloud 自动发布 CSDN 技术博客:把 AI 内容变成可持续获客入口
ai·自动化·csdn·ace data cloud·技术营销
大数据张老师1 个月前
Typora 导出 Word 模版操作手册
开发语言·c#·word·typora