数据库表的设计依据。
设计数据库表时,按照以上的范式进行设计,可以避免表中数据的冗余、空间的浪费。
最核心、最重要的范式,所有表的设计都需要满足该范式。
要求:
我们来看下面这张表:
学生编号 学生姓名 联系方式
--------------------------------------------
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
要求:
我们来看下面这张表:
学生编号 学生姓名 教师编号 教师姓名
---------------------------------------------------
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
口诀:多对多,三张表,关系表两个外键。
要求:
分析下面这张表:
学生编号(PK) 学生姓名 班级编号 班级名称
-----------------------------------------
1001 张三 01 一年一班
1002 李四 02 一年二班
1003 王五 03 一年三班
1004 赵六 03 一年三班
以上表的设计是描述班级和学生之间的关系。
一个班级里有多个学生,是一对多的关系。
是否满足第一范式要求?
? 满足。有主键;所有字段不可再分。
是否满足第二范式要求?
? 满足。主键不是复合主键,没有产生部分依赖。
是否满足第三范式要求?
? 不满足。班级名称依赖班级编号,班级编号依赖学生编号,产生了传递依赖。
? 不符合第三范式的要求,产生了数据冗余。
那么该如何设计一对多呢?
可以分为两个表:
班级表:一
班级编号(pk) 班级名称
------------------------
01 一年一班
02 一年二班
03 一年三班
03 一年三班
学生表:多
学生编号(PK) 学生姓名 班级编号(fk)
----------------------------------
1001 张三 01
1002 李四 02
1003 王五 03
1004 赵六 03
口诀:一对多,两张表,多的表加外键。
一对多:
多对多:
一对一:
一对一拆分表的情况
在实际开发中,可能存在一张表中的字段太多、太庞大的情况。这种时候就需要拆分表。
没拆分前:一张表
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
...
数据库设计三范式是理论上的。
而实践和理论往往有偏差。
比如为了满足客户需求,有时会拿冗余换执行速度。
就比如上面的一些分表操作,虽然减少了内存的浪费,但表一多,连接的次数也就变多了。
在sql中,表与表之间的连接次数越多,效率越低。(笛卡尔积现象)
有时候可能会存在冗余,但为了减少表的连接次数,这样做也是合理的。并且对于开发人员来说,sql语句的编写难度也会降低。
总而言之,一切的最终目的都是满足客户需求。
原文:https://www.cnblogs.com/TSCCG/p/15058743.html