什么是数据库的设计范式
数据库表的设计依据也就是范式
第一范式
要求任何一张表都必须有主键,每一个字段原子性不可分
思考:下面这张表是否属于第一范式?
学生编号 | 学生姓名 | 联系方式 |
---|---|---|
1001 | 张三 | zs@qq,com,1231232131 |
1002 | 李四 | ls@qq.com,3213123123 |
1001 | 王五 | ww@qq,com,3231231313 |
答:不属于,因为没有主键,且联系方式原子性可再分为邮箱和电话
修改之后的表格如下所示才满足第一范式
学生编号(primary key) | 学生姓名 | 邮箱地址 | 联系电话 |
---|---|---|---|
1001 | 张三 | zs@qq,com | 1231232131 |
1002 | 李四 | ls@qq.com | 3213123123 |
1003 | 王五 | ww@qq,com | 3231231313 |
第二范式
建立在第一范式的基础上,要求所有非主键字段完全依赖主键,不要产生部分依赖
学生编号 | 学生姓名 | 教师编号 | 教师姓名 |
---|---|---|---|
1001 | 张三 | 001 | 王老师 |
1002 | 李四 | 002 | 赵老师 |
1003 | 王五 | 001 | 王老师 |
1001 | 张三 | 002 | 赵老师 |
学生老师关系是多对多的关系,一个老师可以对应一个学生,一个学生可以对应一个老师
上面学生老师表不满足第一范式,因为没有主键,此时没有可以使用复合主键,学生编号+教师编号(primary key)
但是,这个时候学习姓名部分依赖主键里面的学生编号,教师姓名部分依赖主键里面的教师编号,不满足第二范式。此时可以拆分成三张表学生表,教师表,关系表
t_student
学生编号(primary key) | 学生姓名 |
---|---|
1001 | 张三 |
1002 | 李四 |
1003 | 王五 |
t_teacher
教师编号(primary key) | 教师姓名 |
---|---|
001 | 王老师 |
002 | 赵老师 |
t_student_teacher_relation
id(primary key) | 学生编号(foreign key) | 教师编号(foreign key) |
---|---|---|
1 | 1001 | 001 |
2 | 1002 | 002 |
3 | 1003 | 001 |
4 | 1001 | 002 |
第三范式
建立在第二范式的基础上,要求所有非主键字段直接依赖主键,不要产生传递依赖
学生编号(primary key) | 学生姓名 | 班级编号 | 班级名称 |
---|---|---|---|
1001 | 张三 | 01 | 一年一班 |
1002 | 李四 | 02 | 一年二班 |
1003 | 王五 | 03 | 一年三班 |
1004 | 赵六 | 03 | 一年三班 |
学生与班级的关系是1对多的关系,一个学生属于一个班级,一个班级里有许多学生
有主键,原子性不可分,满足第一范式
对主键都是完全依赖,满足第二范式
班级名称依赖班级编号,班级编号再依赖学习编号(primary key),班级名称传递依赖于主键,因此不满足第三范式
需要将1对多的表拆分成2张表
t_class
班级编号(primary key) | 班级名称 |
---|---|
01 | 一年一班 |
02 | 一年二班 |
03 | 一年三班 |
t_student
学生编号(primary key) | 学习姓名 | 班级编号(foreign key) |
---|---|---|
1001 | 张三 | 01 |
1002 | 李四 | 02 |
1003 | 王五 | 03 |
1004 | 赵六 | 03 |
数据库设计范式的作用
避免表中数据的冗余,空间的浪费
总结表的设计
1对多
原则:拆分成两张表,多的部分表加外键,如学生班级表拆分,学生为多,班级为1,因此学生表加外键
多对多
原则:拆分成三张表,关系表加两个外键
1对1
原则:拆分成多个表,加外键,外键要唯一
当表的字段比较多时,需要将表拆分
id(primary key) | login_name | real_name | login_password | |
---|---|---|---|---|
1 | TXzhangsan | 张三 | 123456 | zx@qq.com |
2 | TXlisi | 李四 | 123456 | ls@qq.com |
3 | TXwangwu | 王五 | 123456 | ww@qq.com |
拆分成两张表
t_login
主键尽量使用自然主键,不要使用login_name业务主键
login_id(primary key) | login_name | login_password |
---|---|---|
1 | TXzhangsan | 123456 |
2 | TXlisi | 123456 |
3 | TXwangwu | 123456 |
t_user
id(primary key) | real_name | login_id(foreign key + unique) | |
---|---|---|---|
1 | 张三 | zs@qq.com | 1 |
2 | 李四 | ls@qq.com | 2 |
3 | 王五 | ww@qq.com | 3 |
现实与实际
数据库三范式是理论上的,实际开发时,多表连接查询是会影响效率的,表连接越多效率相对越低,开发时需要在空间和效率两者中进行选择。