赞
踩
在设计表之前,我们需要从需求中获得实体(实体就是一张张表),实体的属性就是表中的字段(列),然后确定实体与实体之间的关系,最后使用 SQL 语句去创建具体的表
在设计表的时候我们会遵守一些规则,这些规则叫做三大范式(范式是描述数据关系的模型),下面我们来了解一下三大范式。
第一范式是关系型数据库的一个基本要求,如果不满足第一范式就不是关系型数据库。
第一范式要求表里的字段不能继续拆分
举个例子:
我们定义一个学生表,但是你只是给了一个字段——学生,可是这个学生范围很广泛,有学生的姓名,性别,年龄,班级,学号等等,说明学生这个字段是可以拆分的,所以你最开始定义的表是不符合第一范式的。
如果一张表里的所有的字段都无法拆分那就满足第一方式,还是学生表为例子:现在创建了学号,姓名,性别,年龄这四个字段组成学生表那就符合第一范式,因为每一个字段都是不可分的。
在定义表的时候,对照数据中的数据类型,将每一个字段都可以用一个数据类型表示,那么当前这个表就天然满足第一范式
第二范式在满足第一范式的基础上,存在于复合主键的情况下,不存在非关键字段对任意候选键的部分函数依赖
简单来说,对于由两个或者多个关键字段(即复合主键)决定一条记录的情况的时候,如果一行数据中非主键的字段与复合主键的部分字段存在关系,就说明存在部分函数依赖,不满足第二范式
现在举个例子:
假设我有一张学生成绩表,表里有一下这些字段:
这张表设计是存在问题的,首先我们可以假设将学号设置为主键,然后通过学号我们是可以确定这个学生的姓名性别年龄以及班级的,但是再往后看,我们会发现通过课程名称我们应该是可以找到课程的学分,这时候这个课程的成绩到底是由什么决定的,那应该就是学生和课程共同决定的(学生参加这个课程的考试之后就会有成绩),那这时候我们就可以将学号和课程名称定义为复合主键,在这张表中姓名和课程学分就是非关键字段,但是却与候选键发生了函数依赖(也就是存在关系),那么就会违反第二范式。
以上面的学生成绩表为例:
将表进行拆分,学生表(学生学号,姓名,性别,年龄与班级),课程表(课程编号、名称,课程学分),还有一张课程成绩表(学号,课程编号,成绩)。
如果一张表没有复合主键,那么这张表一定满足第二范式。
如果不满足第二范式有什么后果?
如何避免第二范式:
在设计复合主键的时候,一定要考虑清楚其他字段会不会与复合存在部分函数联系。
第三范式在第二范式的基础上,不存在非关键字段对任一候选键存在传递依赖。
以下面的学生表为例:
这张表主键定义为学号,但是我们可以 从学号得知学院名称 再得知学院的地址和电话,由于学院名称是非关键字段,所以存在了传递关系。
那该如何设计这张学生表?
设计成两张表,一个学院表(学院编号,学院名称,学院电话,学院地址)
一张学生表(学号,姓名,学院编号)设计成主外键键关系即可。
举个例子:一个中国公民只有一个身份证
如何设计表:
创建两张表,分别记录中国公民的个人信息(姓名,电话,现居地址),身份证信息(身份证号,姓名,年龄,性别)
然后我们可以再公民表中设计一个外键(身份证号)。
create table idcard(
id bigint primary key comment '身份证号',
name varchar(20) not null comment '姓名',
gender varchar(1) not null comment '性别',
age int not null comment '年龄'
);
create table person(
id bigint primary key auto_increment comment '编号',
name varchar(20) not null comment '姓名',
address varchar(100) comment '现居地址',
foreign key (id) references idcard(id)
);
举例:一个班级存在很多个学生,这是一对多的关系
同理,很多个学生都在一个班级,这是多对一的关系
如何设计表:
还是一样,先创建不同的实体表,再去建立联系
演示:创建班级表(班级编号,班级人数)
再创建学生表(学生学号,姓名,年龄,所属班级)
最后确定关系,我们可以在学生表添加一个班级外键:
create table class(
id bigint primary key comment '班级编号',
num int comment '人数'
);
create table student (
id bigint primary key auto_increment comment '学生学号',
name varchar(50) not null comment '姓名',
age int comment '年龄',
foreign key (id) references class(id)
);
举个例子:学生与课程的关系,一个学生可以选择很多个课程,一个课程同时也可以包含很多个学生。
如何设计?
首先分别创建好实体表,一张学生表(学生学号,姓名,年龄) 一张课程表(课程编号,课程名称,课程学分)
然后确定关系发现是多对多,那就再创建一张表——关系表(关系表自身的编号,学生学号,课程编号)
create table student ( id bigint primary key auto_increment comment '学生学号', name varchar(50) not null comment '姓名', age int comment '年龄' ); create table course( id bigint primary key auto_increment comment '课程编号', name varchar(20) not null comment '课程名称', score decimal(2,1) comment '学分' ); create table student_course ( id bigint primary key comment '自身编号', student_id bigint not null comment '学生学号', course_id bigint not null comment '课程编号', foreign key (student_id) references student(id), foreign key (course_id) references course(id) );
我们还可以在这张关系表中添加一个成绩的字段。
对于没有关系的表,我们直接设计即可,不需要考虑其与其他的关系(因为本来就没有关系)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。