数据库设计三范式
1.0什么设计范式?
设计表的依据,按照这三范式设计设计的表不会出现数据冗余.
复习一下数据依赖 :
-
完全依赖: 通过{学生学号, 选修课程名}可以得到{该生本门选修课程的成绩},而通过单独的{学生学号}或者单独的{选修课程名}都无法得到该成绩,则说明{该生本门选修课程的成绩}完全依赖于{学生学号,选修课程名}
-
部分函数依赖: 通过{学生学号,课程号}可以得到{该生姓名},而通过单独的{学生学号}已经能够得到{该生姓名},则说明{该生姓名}部分依赖于{学生学号,课程号}; 又比如, 通过{学生学号,课程号}可以得到{课程名称},而通过单独的{课程号}已经能够得到{课程名称},则说明{课程名称}部分依赖于{学生学号,课程号}。(部分依赖会造成数据冗余及各种异常。)
-
传递函数依赖: 在关系R(学号,宿舍,费用)中,通过{学号}可以得到{宿舍},通过{宿舍}可以得到{费用},而反之都不成立,则存在传递依赖{学号}->{费用}。(传递依赖也会造成数据冗余及各种异常。)
1.1三范式都是那些?
-
第一范式:任何一张表都要有主键,并且每一个字段原子性不可再分
-
第二范式:在第一范式基础上,所有非主键字段完全依赖主键,不能产生部分依赖
(注意这里要减少复合主键的使用)
会出现数据冗余,空间浪费;怎么解决?
记住口诀: 多对多,三张表,关系表,两个外键
t_student学生表
sno(PK) | sname |
---|---|
1 | 张三 |
2 | 李四 |
3 | 王五 |
t_teacher讲师表
tno(PK) | tname |
---|---|
1 | 王老师 |
2 | 张老师 |
3 | 李老师 |
t_student_teacher_relation
id(pk) | sno(FK) | tno(FK) |
---|---|---|
1 | 1 | 3 |
2 | 1 | 2 |
3 | 2 | 3 |
4 | 2 | 1 |
5 | 3 | 2 |
6 | 3 | 1 |
- 第三范式:建立在第二范式的基础之上,所有的非主键字段直接依赖主键,不能产生传递依赖
满足第三范式(3NF)必须先满足第二范式(2NF)。在满足第二范式的基础上,切不存在传递函数依赖,那么就是第三范式。简而言之,第三范式就是属性不依赖于其它非主属性。
记住口诀: 多对多,三张表,关系表,两个外键
记住口诀: 一对多,两张表,多的表,加外键
班级表t_class
cno(PK) | cname |
---|---|
1 | 班级1 |
2 | 班级2 |
学生表t_student
sno(PK) | sname | classno(fk) |
---|---|---|
101 | 张一 | 1 |
102 | 张二 | 1 |
103 | 张三 | 2 |
104 | 张四 | 2 |
105 | 张五 | 2 |
这里所解决的就是消除传递函数依赖
提醒一下:实际开发中,以满足客户的需求为主,有时候会拿冗余换执行速度
1.2一对一怎么设计?
简单用户设计方案:
设计用户登录表t_user_login
id(PK) | username | password |
---|---|---|
1 | zs | 123 |
2 | ls | 456 |
用户详细表设计t_user_detail
id(PK) | realname | tel |
---|---|---|
张三 | 11111100 | |
李四 | 11111122 |
怎么设计?
两种设计方案:
主键共享方案:
id(PK+fk) | realname | tel |
---|---|---|
张三 | 11111100 | |
李四 | 11111122 |
外键唯一:
id(PK) | realname | tel | userid(FK+Unique) |
---|---|---|---|
张三 | 11111100 | ||
李四 | 11111122 |