三范式
什么是数据库设计范式
数据库表的设计依据 如何进行数据库表的设计
第一范式
要求任何一张表必须要有主键 每一个字段原子性不可再分
第二范式
建立在第一范式基础之上 要求所有非主键字段完全依赖主键 不要产生部分依赖
第三范式
建立在第二范式基础之上 要求所有非主键字段直接依赖主键 不要产生传递依赖
按照以上的范式进行 可以避免表中数据的冗余、空间的浪费
第一范式
最核心、最重要的范式 所有表的设计都需要满足
必须要有主键 并且每一个字段都是原子性不可再分
第一:没有主键
第二:联系方式可以分为邮箱地址和电话(可再分)
可以这样改
那姓名里的姓和名也可以再分呀
所谓不可再分不是说一定要强行去拆分
要符合逻辑 强行把姓名拆开来当然可以 但那样逻辑反而混乱了 没有意义
关于第一范式,每一行必须唯一,也就是每个表必须有主键,这是我们数据库设计的最基本要求,主要通常采用数值型或定长字符串表示,关于列不可再分,应该根据具体的情况来决定。如联系方式,为了开发上的便利行可能就采用 一个字段了。
(实际上主键一般不用有实际意义的字段 因为ssssvip可能会有改卡号的需求……)
第二范式
建立在第一范式的基础之上
要求所有非主键字段 必须完全依赖主键 不要产生部分依赖
比如一张老师学生关系表
首先就不满足第一范式——没有主键
可以设置联合主键PK(学生编号,教师编号)
现在它满足第一范式 那么它满足第二范式吗
部分依赖——
张三依赖的是1001,王老师依赖的是001
他们都只依赖于主键的一部分
所以不满足第二范式
缺点是什么?数据冗余、空间浪费
——张三重复了、王老师也重复了……
那该怎么改
考虑一下学生老师的关系——
一个学生对应多个老师 一个老师对应多个学生 多对多关系
其实在前面E-R图里也有接触过这种概念 对于多对多的联系 一般会采取一个中间量
用这个思路——使用三张表来表示多对多的关系
如果一个表是单一主键,那么它就复合第二范式,部分依赖和主键有关系
这是典型的“多对多”的设计
多对多,三张表——关系表俩外键
第三范式
建立在第二范式的基础上
要求所有非主键字段必须直接依赖主键 不用产生传递依赖
满足第一范式 有主键
满足第二范式 (班级和学生的关系——一对多 一个班级多个学生)
它是单一主键 不是复合主键 没产生部分依赖 所有的都依赖于学生编号
满足第三范式吗?
传递依赖——
一年一班依赖01,01依赖1001 产生了传递依赖
不符合第三范式要求
产生了数据的冗余
又该怎么改?
从上表可以看出,班级名称字段存在冗余,因为班级名称字段没有直接依赖于主键,班级名称字段依赖于班级编号,班级编号依赖于学生编号,那么这就是传递依赖,解决的办法是将冗余字段单独拿出来建立表
这是典型的一对多,一存储在一张表中,多存储在一张表中,在多的那张表中添加外键指向一的一方的主键
一对多
两张表 多的表加外键
总结
第一范式:有主键,具有原子性,字段不可分割
第二范式:完全依赖,没有部分依赖
第三范式:没有传递依赖
数据库设计尽量遵循三范式,但是还是根据实际情况进行取舍,有时可能会拿冗余换速度,最终用目的要满足客户需求(理论与实践)
避免冗余就拆开表 拆开表但是需要表连接 表连接一多因为笛卡尔积现象速度就越慢
所以这还是时间和空间的一个取舍问题
实际上可能会存在一张表字段太多 太庞大
对于一对一的关系也可能需要拆分
两种方案:
第一种设计方案:主键共享 (用得较少)
第二种设计方案:外键唯一
对于
t_user
| id | login_name | login_pwd | real_name | 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 | address | sex | login_id(fk+unique) | |
| 100 | 张三 | zhangsan@xxx | 上海 | 男 | 1 |
| 200 | 李四 | lisi@xxx | 北京 | 女 | 2 |
| …… |
在一个表上多加一列外键 并加上唯一性约束 实现的功能就使得两个表的字段联系上
so
一对一 拆分表 外键唯一
一对多 两张表 多的表加外键
多对多 三张表 关系表俩外键
tips:
💬 评论