三范式

什么是数据库设计范式

数据库表的设计依据 如何进行数据库表的设计

第一范式

要求任何一张表必须要有主键 每一个字段原子性不可再分

第二范式

建立在第一范式基础之上 要求所有非主键字段完全依赖主键 不要产生部分依赖

第三范式

建立在第二范式基础之上 要求所有非主键字段直接依赖主键 不要产生传递依赖

按照以上的范式进行 可以避免表中数据的冗余、空间的浪费

第一范式

最核心、最重要的范式 所有表的设计都需要满足

必须要有主键 并且每一个字段都是原子性不可再分

image-d062124f

第一:没有主键

第二:联系方式可以分为邮箱地址和电话(可再分)

可以这样改

image-a3dd73d6

那姓名里的姓和名也可以再分呀

所谓不可再分不是说一定要强行去拆分

要符合逻辑 强行把姓名拆开来当然可以 但那样逻辑反而混乱了 没有意义

关于第一范式,每一行必须唯一,也就是每个表必须有主键,这是我们数据库设计的最基本要求,主要通常采用数值型或定长字符串表示,关于列不可再分,应该根据具体的情况来决定。如联系方式,为了开发上的便利行可能就采用 一个字段了。

(实际上主键一般不用有实际意义的字段 因为ssssvip可能会有改卡号的需求……)

第二范式

建立在第一范式的基础之上

要求所有非主键字段 必须完全依赖主键 不要产生部分依赖

比如一张老师学生关系表

image-4c815caa

首先就不满足第一范式——没有主键

可以设置联合主键PK(学生编号,教师编号)

image-d76d6f27

现在它满足第一范式 那么它满足第二范式吗

部分依赖——

张三依赖的是1001,王老师依赖的是001

他们都只依赖于主键的一部分

所以不满足第二范式

缺点是什么?数据冗余、空间浪费

——张三重复了、王老师也重复了……

那该怎么改

考虑一下学生老师的关系——

一个学生对应多个老师 一个老师对应多个学生 多对多关系

其实在前面E-R图里也有接触过这种概念 对于多对多的联系 一般会采取一个中间量

image-89f8465e

用这个思路——使用三张表来表示多对多的关系

image-2b24aaca image-577d4098 image-c773fdb3

如果一个表是单一主键,那么它就复合第二范式,部分依赖和主键有关系

这是典型的“多对多”的设计

多对多,三张表——关系表俩外键

第三范式

建立在第二范式的基础上

要求所有非主键字段必须直接依赖主键 不用产生传递依赖

image-72eb9506

满足第一范式 有主键

满足第二范式 (班级和学生的关系——一对多 一个班级多个学生)

它是单一主键 不是复合主键 没产生部分依赖 所有的都依赖于学生编号

满足第三范式吗?

传递依赖——

一年一班依赖01,01依赖1001 产生了传递依赖

不符合第三范式要求

产生了数据的冗余

又该怎么改?

从上表可以看出,班级名称字段存在冗余,因为班级名称字段没有直接依赖于主键,班级名称字段依赖于班级编号,班级编号依赖于学生编号,那么这就是传递依赖,解决的办法是将冗余字段单独拿出来建立表

image-6397e6d1 image-594d5695

这是典型的一对多,一存储在一张表中,多存储在一张表中,在多的那张表中添加外键指向一的一方的主键

一对多

两张表 多的表加外键

总结

第一范式:有主键,具有原子性,字段不可分割

第二范式:完全依赖,没有部分依赖

第三范式:没有传递依赖

数据库设计尽量遵循三范式,但是还是根据实际情况进行取舍,有时可能会拿冗余换速度,最终用目的要满足客户需求(理论与实践)

避免冗余就拆开表 拆开表但是需要表连接 表连接一多因为笛卡尔积现象速度就越慢

所以这还是时间和空间的一个取舍问题

实际上可能会存在一张表字段太多 太庞大

对于一对一的关系也可能需要拆分

两种方案:

第一种设计方案:主键共享 (用得较少)

第二种设计方案:外键唯一

对于

t_user

id login_name login_pwd real_name email address sex
1 zhangsan 123 张三 zhangsan@xxx 上海
2 lisi 123 李四 lisi@xxx 北京
……

拆成登入信息和详细信息

t_login

id(PK) login_name login_pwd
1 zhangsan 123
2 lisi 123
……

t_user

id(PK) real_name email address sex login_id(fk+unique)
100 张三 zhangsan@xxx 上海 1
200 李四 lisi@xxx 北京 2
……

在一个表上多加一列外键 并加上唯一性约束 实现的功能就使得两个表的字段联系上

so

一对一 拆分表 外键唯一

一对多 两张表 多的表加外键

多对多 三张表 关系表俩外键

tips:

image-d653f2c5

⬅️ 04-设计数据库 🏠 00-数据库 ➡️ 06-表的管理