1.什么是数据库设计范式?
数据库表的设计依据。
2.数据库设计三范式各自的要求
- 数据库设计第一范式:
- 要求任何一张表都必须有主键。
- 每一个字段都要具有原子性,不可再分。
- 数据库设计第二范式:
- 建立在第一范式基础上。
- 要求所有非主键字段完全依赖主键,不要产生部分依赖。
- 数据库设计第三范式:
- 建立在第二范式基础上。
- 要求要求所有非主键字段直接依赖主键,不要产生传递依赖。
设计数据库表时,按照以上的范式进行设计,可以避免表中数据的冗余、空间的浪费。
3.数据库设计第一范式
最核心、最重要的范式,所有表的设计都需要满足该范式。
要求:
- 必须有主键。
- 每一个字段都要具备原子性,不可再分。
我们来看下面这张表:
学生编号 学生姓名 联系方式
--------------------------------------------
1001 张三 zs@qq.com,12345555555
1002 李四 li@163.com,12131466666
1001 王五 ww@qq.com,17888888888
这张表明显不符合第一范式的要求:
- 学生编号有重复的,没有主键。
- 联系方式可再分为邮箱和电话,不具备原子性。
按照第一范式进行更改:
学生编号(pk) 学生姓名 邮箱地址 电话号码
---------------------------------------------
1001 张三 zs@qq.com 12345555555
1002 李四 li@163.com 12131466666
1003 王五 ww@qq.com 17888888888
4.数据库设计第二范式
要求:
- 建立在第一范式基础上。
- 要求所有非主键字段完全依赖主键,不要产生部分依赖。
我们来看下面这张表:
学生编号 学生姓名 教师编号 教师姓名
---------------------------------------------------
1001 张三 001 王老师
1002 李四 002 赵老师
1003 王五 001 王老师
1001 张三 002 赵老师
这张表描述了学生和教师的关系:(1个学生可能有多个老师,1个老师有多个学生)
是非常典型的:多对多关系。
分析是否符合第一范式要求:不符合,没有主键。
按照第一范式的要求修改:
学生编号 + 教师编号(pk) 学生姓名 教师姓名
---------------------------------------------------
1001 001 张三 王老师
1002 002 李四 赵老师
1003 001 王五 王老师
1001 002 张三 赵老师
将学生编号和教师编号两个字段联合起来做主键,复合主键(pk:学生编号+教师编号)
经过修改之后,符合了第一范式要求,但符合第二范式要求吗?
明显不符合。可以看到,修改后的表中,学生姓名依赖学生编号,教师姓名依赖教师编号,产生了部分依赖。
部分依赖的缺点:数据冗余、空间浪费。“张三”重复了,“王老师”重复了。
为了让上面的表满足第二范式,需要如下设计:
使用三张表来表示多对多的关系:
-
学生表
学生编号(pk) 学生姓名 ----------------------- 1001 张三 1002 李四 1003 王五
-
教师表
教师编号(pk) 教师姓名 ----------------------- 001 王老师 002 赵老师
-
学生教师关系表
id(pk) 学生编号(fk) 教师编号(fk) --------------------------------------- 1 1001 001 2 1002 002 3 1003 001 4 1001 002
口诀:多对多,三张表,关系表两个外键。
5.数据库设计第三范式
要求:
- 建立在第二范式基础上。
- 要求要求所有非主键字段直接依赖主键,不要产生传递依赖。
分析下面这张表:
学生编号(PK) 学生姓名 班级编号 班级名称
-----------------------------------------
1001 张三 01 一年一班
1002 李四 02 一年二班
1003 王五 03 一年三班
1004 赵六 03 一年三班
以上表的设计是描述班级和学生之间的关系。
一个班级里有多个学生,是一对多的关系。
是否满足第一范式要求?
满足。有主键;所有字段不可再分。
是否满足第二范式要求?
满足。主键不是复合主键,没有产生部分依赖。
是否满足第三范式要求?
不满足。班级名称依赖班级编号,班级编号依赖学生编号,产生了传递依赖。
不符合第三范式的要求,产生了数据冗余。
那么该如何设计一对多呢?
可以分为两个表:
-
班级表:一
班级编号(pk) 班级名称 ------------------------ 01 一年一班 02 一年二班 03 一年三班 03 一年三班
-
学生表:多
学生编号(PK) 学生姓名 班级编号(fk) ---------------------------------- 1001 张三 01 1002 李四 02 1003 王五 03 1004 赵六 03
口诀:一对多,两张表,多的表加外键。
6.总结
-
一对多:
- 一对多,两张表,多的表加外键。
-
多对多:
- 多对多,三张表,关系表两个外键。
-
一对一:
-
一对一拆分表的情况
-
在实际开发中,可能存在一张表中的字段太多、太庞大的情况。这种时候就需要拆分表。
-
没拆分前:一张表
t_user:
id login_name login_pwd real_name email address... ------------------------------------------------------------------------------- 1 zhangsan 123456 张三 zs@qq.com 北京 2 lisi 123456 李四 ls@qq.com 上海 3 wangwu 123456 王五 ww@163.com 广州 ...
这种庞大的表建议拆分成两张:
t_login:登录信息表
id(pk) login_name login_pwd ---------------------------------- 1 zhangsan 123456 2 lisi 123456 3 wangwu 123456 ...
t_user:用户详细信息表
id(pk) real_name email address ... login_id(fk+unique) ------------------------------------------------------------------------------- 1001 张三 zs@qq.com 北京 1 1002 李四 ls@qq.com 上海 2 1003 王五 ww@163.com 广州 3 ...
-
-
7.以满足客户需求为基准
数据库设计三范式是理论上的。
而实践和理论往往有偏差。
比如为了满足客户需求,有时会拿冗余换执行速度。
就比如上面的一些分表操作,虽然减少了内存的浪费,但表一多,连接的次数也就变多了。
在sql中,表与表之间的连接次数越多,效率越低。(笛卡尔积现象)
有时候可能会存在冗余,但为了减少表的连接次数,这样做也是合理的。并且对于开发人员来说,sql语句的编写难度也会降低。
总而言之,一切的最终目的都是满足客户需求。