数据库设计
多表之间的关系
-
关系分类
-
一对一
如人和身份证。一个人只有一个身份证
-
一对多
如学生和院系。一个学生属于一个院系,而一个院系有很多个学生
-
多对多
如学生和课程。一个学生可以选择多门课程,一门课程也可以被多个学生选择
-
-
实现关系
-
一对多
在多的一方,建立外键字段,指向一的一方的主键。如在学生表中建立外键字段dep_id,指向院系表中的主键id
-
多对多
建立一个中间表,中间表中至少包含2个字段,这2个字段分别指向两张关联表的主键。这2个字段一起,作为中间表的联合主键
-
一对一
在任意一方添加外键字段(外键字段要有唯一约束),指向另一方的主键即可
-
三大范式
概念
设计数据库表时,需要遵循的一些规范。
设计关系型数据库时,遵循不同的规范要求,设计出合理的关系型数据库,这些规范要求被称为范式,各种范式呈递次规范,越高的范式,数据库冗余越小。递次规范指的是:后面的范式要求,包含了前面的范式要求。即,若要遵循2NF,则必须先遵循1NF。
分类
目前,关系型数据库有6种范式:第一范式(1NF),第二范式(2NF),第三范式(3NF),巴斯-科德范式(BCNF),第四范式(4NF),第五范式(5NF,又称完美范式)
第一范式(1NF)
每一列都是不可分割的原子数据项
第二范式(2NF)
在1NF基础上,非码属性必须完全依赖于候选码(在1NF基础上,消除非主属性对主码的部分函数依赖)
一些概念说明:
-
函数依赖
A-->B
,若通过A属性(属性组),可以唯一确定B属性的值,则称B依赖于A。例如,
学号-->姓名
,(学号,课程名称) --> 分数
-
完全函数依赖
A-->B
,若A是一个属性组,则B属性的确定需要依赖于A属性组中所有的属性。例如,(学号,课程名称)
被分数
完全依赖 -
部分函数依赖
A-->B
,若A是一个属性组,则B属性的确定只需要依赖A属性组中的部分属性即可。(学号,课程名称) --> 姓名
。 姓名的确认只需要学号
一个属性就够了 -
传递函数依赖
A-->B
,B-->C
,如果通过A属性(属性组)的值,可以唯一确定B属性的值,再通过B属性的值可以唯一确定C属性的值。学号 --> 院系
,院系 --> 教授名
,则教授名
传递依赖于学号
-
码
如果在一张表中,一个属性,或属性组,被其他所有属性依赖,则称这个属性,或属性组,为这张表的码
- 主属性:码属性组中所有的属性
- 非主属性:其他属性
第三范式(3NF)
在2NF基础上,任何非主属性,不依赖于其他非主属性(在2NF基础上,消除传递依赖)
案例
学号 | 姓名 | 院系 | 课程 | 分数 |
---|---|---|---|---|
1000 | 阿狸 | 表演系-强森 | 高数 | 90 |
1001 | 拉克丝 | 播音系-罗宾 | 英语 | 99 |
1002 | 阿卡丽 | 体育系-汤姆 | 高数 | 89 |
1003 | 劫 | 体育系-汤姆 | 英语 | 120 |
1000 | 阿狸 | 表演系-强森 | 计算机 | 20 |
上面的数据库表,院系这一栏,包含了院系名称和院系教授,明显是可分割的数据项,不满足第一范式。改动后如下。
学号 | 姓名 | 院系 | 教授 | 课程 | 分数 |
---|---|---|---|---|---|
1000 | 阿狸 | 表演系 | 强森 | 高数 | 90 |
1001 | 拉克丝 | 播音系 | 罗宾 | 英语 | 99 |
1002 | 阿卡丽 | 体育系 | 汤姆 | 高数 | 89 |
1003 | 劫 | 体育系 | 汤姆 | 英语 | 120 |
1000 | 阿狸 | 表演系 | 强森 | 计算机 | 20 |
但是仍然存在问题
-
数据存在冗余(数据重复),如学号,姓名,院系,教授等
-
添加数据有问题,若要开设一个新的院系,但该院系还没开始招生,则无法添加
-
删除数据也有问题,如果某个学生毕业了,把他的数据删掉,则会删掉院系信息。
根据第二范式,进行拆表。
学生表
学号 | 姓名 | 院系 | 教授 |
---|---|---|---|
1000 | 阿狸 | 表演系 | 强森 |
1001 | 拉克丝 | 播音系 | 罗宾 |
1002 | 阿卡丽 | 体育系 | 汤姆 |
1003 | 劫 | 体育系 | 汤姆 |
课程表
学号 | 课程名称 | 分数 |
---|---|---|
1000 | 高数 | 90 |
1001 | 英语 | 99 |
1002 | 高数 | 89 |
1003 | 英语 | 120 |
1000 | 计算机 | 20 |
拆完表后,学生表的码为学号,其他属性完全依赖于学号;课程表的码为(学号,课程名称),其他属性完全依赖于该码。(消除了非主属性对主属性的部分依赖)
数据冗余解决一些了,但数据的添加和删除仍然存在问题。比如新增一个院系,或某个同学毕业了要删除其记录。
看学生表内,教授依赖于院系,院系依赖于学号,教授和学号之间是传递依赖关系。根据第三范式,对学生表进行拆分,消除传递依赖。将学生表拆称学生表和院系表
学生表
学号 | 姓名 | 院系 |
---|---|---|
1000 | 阿狸 | 表演系 |
1001 | 拉克丝 | 播音系 |
1002 | 阿卡丽 | 体育系 |
1003 | 劫 | 体育系 |
院系表
院系 | 教授 |
---|---|
表演系 | 强森 |
播音系 | 罗宾 |
体育系 | 汤姆 |
如此以来,就遵循了第三范式。可以新增新开设的院系和教授,学生毕业后,直接删除学生记录,不会清除掉院系的信息。数据冗余,添加数据,删除数据这三个问题都解决了。