数据库设计三范式
设计范式讨论的问题:如何进行数据库表的设计,可以避免表中数据冗余和空间浪费
第一范式
最核心最重要的范式
任何一张表必须有主键,每一个字段具有原子性,不可再分
注意:主键是不可重复的,如果某字段的值重复出现,则该字段不是主键,不满足第一范式
第二范式
在第一范式的基础上,要求所有非主键字段完全依赖主键,不要产生部分依赖
这种情况下复合主键产生了部分依赖:学生姓名依赖学生编号,教师姓名依赖教师编号;此时出现了数据的冗余
学生编号+教师编号(pk) 学生姓名 教师姓名
------------------------------------------------------
1001 001 张三 王老师
1002 002 李四 赵老师
1003 001 王五 王老师
1001 002 张三 赵老师
多对多:需要修改为以下格式,用三张表表示多对多的关系
学生编号(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 一年三班
学生表:多
学生编号(PK) 学生姓名 班级编号(fk)
--------------------------------------
1001 张三 01
1002 李四 02
1003 王五 03
1004 赵六 03
一对多的情况时,将传递连接的列分开成两张表,多的表加外键
一对一设计
较为庞大的表建议拆分成两张表(不建议共享主键,否则查询会耗费较多时间)
拆分前
t_user
id login_name login_pwd real_name email address........
---------------------------------------------------------------------------
1 zhangsan 123 张三 zhangsan@163
2 lisi 123 李四 lisi@126
拆分后
t_login 登录信息表
id(pk) login_name login_pwd
---------------------------------
1 zhangsan 123
2 lisi 123
t_user 用户详细信息表
id(pk) real_name email ........
----------------------------------------------
100 张三 zhangsan@163 1
200 李四 lisi@126 2
这样,登陆和访问修改用户信息时就可以分开访问两张不同表,提升查询效率
一对一时,外键唯一即可
Notice
-
数据库设计三范式是理论上的
-
实践和理论有的时候有偏差
-
最终的目的都是为了满足客户的需求,有的时候会拿冗余换执行速度
-
因为在sql当中,表和表之间连接次数越多,效率越低(笛卡尔积)
-
有的时候可能会存在冗余,但是为了减少表的连接次数,但这样做也是合理的,并且对于开发人员来说,sql语句的编写难度也会降低