范式:数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系。所以建立科学的,规范的的数据库是需要满足一些。规范的来优化数据数据存储方式。在关系型数据库中这些规范。
第一范式:数据库表中的字段都是单一属性的,不可再分。简单的说,每一个属性都是原子项,不可分割。
1NF是关系模式应具备的最起码的条件,如果数据库设计不能满足第一范式,就不称为关系型数据库。也就是说,只要是关系型数据库,就一定满足第一范式。
1 ceate table 学生( 2 学号 number , 3 姓名 varchar2(10), 4 年龄 varchar2(2), 5 联系方式 varchar(200) 6 );
联系方式会有很多,可能包含:地址、电话、邮编、email和QQ等等,所以联系方式可以再分,这样的设计不符合第一范式。
1 create table 学生选课( 2 学生编号 number primary key, 3 学生姓名 varchar2(20), 4 学生年龄 number, 5 课程名称 varchar2(50), 6 课程学分 number, 7 考试成绩 number 8 ); 9 insert into(学生编号,学生姓名,学生年龄,课程名称,课程学分,考试成绩)values(1,'张三',20,‘java',2,89); 10 insert into(学生编号,学生姓名,学生年龄,课程名称,课程学分,考试成绩)values(2,'李四',20,‘Oracle',1,78); 11 insert into(学生编号,学生姓名,学生年龄,课程名称,课程学分,考试成绩)values(1,'张三',20,‘Oracle',1,90);
此时的设计包含有如下的问题:
- 主键信息重复或者说无法确定主键;
- 学生、课程信息重复(有可能会更新很多的数据);
- 如果某一门课程没人选择参加,那么课程就没了。
所以此时利用第一范式没有办法解决当前设计问题,改成多对多,成为第二范式。
第二范式:(多对多)数据表中不存在非关键字段对任意一候选关键字段的部分函数依赖。
- 先通过函数关系进行面描述
- 函数依赖指的式某几个字段的集合是否可以推到出其他列的内容。(如果一个表中某一个字段A的值是由另外一个字段或一组字段B的值来确定的,就称为A函数依赖于B。)
学生表:
1 create table学生( 2 学生编号 mid primary key, 3 学生姓名 varchar2(20), 4 学生年龄 number 5 )
课程表:
1 create table 课程( 2 课程编号 cid primary key, 3 课程名称 varchar2(50), 4 课程学分 number 5 )
学生_课程表:
1 create table 学生_课程( 2 学生编号 mid references... 3 课程编号 cid references... 4 5 )
第三范式:(一对多)
数据表之中不存在非关键字段对任意一候选关键字段传递函数依赖。目标是确保每列都和主键列直接相关,而不是间接相关。
传递依赖是什么意思?现在建立一张雇员表。
雇员编号 | 姓名 | 部门 | 位置 | 工资 |
1 | 张三 | 测试部 | 上海 | 1000 |
其中存在一个传递依赖:利用编号与姓名可以确定一个雇员的部门,但是通过部门名称又可以找到公司位置。这个称谓传递函数依赖。
现有一个学校有多个学生。如果使用第一设计范式,描述出一个学校有多个学生,但同时又会描述一个学生属于多个学生。所以可以使用第三设计范式。
1 create table 学校( 2 学校编号 number primary key 3 名称 varchar2(50) 4 ); 5 6 create table 学生( 7 学生编号 mid primary key, 8 学生姓名 varchar2(20), 9 学生年龄 number 10 学校编号 number references... 11 );
注:关系实质上是一张二维表,其中每一行是一个元组,每一列是一个属性。
数据不能存在传递关系,即没个属性都跟主键有直接关系而不是间接关系。像:a-->b-->c 属性之间含有这样的关系,是不符合第三范式的。
再比如Student表(学号,姓名,年龄,性别,所在院校,院校地址,院校电话)
这样一个表结构,就存在上述关系。 学号--> 所在院校 --> (院校地址,院校电话)
这样的表结构,我们应该拆开来,如下。
(学号,姓名,年龄,性别,所在院校)--(所在院校,院校地址,院校电话)
总结:三个设计范式只是一个设计初的思考方式。但是在实际运行中,这三个必须要打破。