MySQL:表设计
表的设计
从需求中获得类,类对应到数据库中的实体,实体在数据库中表现为一张一张的表,类中的属性就对应着表中的字段(也就是表中的列)
表设计的三大范式:
在数据库设计中,三大范式(3NF)用于确保数据的结构清晰、冗余较少,并且维护数据的一致性。
第一范式
关系型数据库中最基本的要求,不满足第一范式就不可以被称关系型数据库。
要求:表里的字段不能进行继续的拆分
举例(设计一个学生表)
错误形式:
像这样的表,学校列还可以进行拆分,并且并没有一个数据类型来显示学校,我们也可以单独的把学校建成一个表,在两个表中建立关系即可,可以拆分的表在关系型数据库中是绝对不能存在的。
正确形式:
像这样的表就无法进行拆分,每一个列都可以使用一个数据类型表示,满足第一范式的要求。
第二范式
在满足第一范式的前提下,所有非主属性(即非关键字字段)必须完全依赖于整个主键,而不能只是部分依赖于主键。
要求:去除部分依赖,即字段只能依赖于主键的全部,而不是主键的一部分。
举例(学生可以选修课程,课程有对应的学分,学生考试后每一门选修科目有对应的成绩,用数据库中的表记录学生的成绩)
错误形式:
学号 姓名 年龄 课程名 学分 成绩
123 xiaoli 15 数学 80 94
注:
学生相关的信息通过学号来确定,学分通过课程确定,成绩由学号和课程名共同确定。
说明学号和课程名作为复合主键来确定学生的成绩
但是学生的姓名和年龄只由学号决定,学分只有课程决定。
对于这种被两个或者多个关键字段决定一条记录,但是其中又有些记录只被一个关键字段决定的情况我们称之为部分函数依赖,不满足第二范式。
正确形式:
学生表
学号 姓名 年龄
课程表
课程编号 课程名 学分
选修成绩
学号 课程编号 成绩
这样的设计则满足第二范式的要求
注:如果一个表中无复合主键,那么这种表是天然满足第二范式。
不满足第二范式可能出现的问题:
1.数据冗余
由于非主属性只依赖主键的一部分,会导致数据重复存储
学生的姓名,年龄,学分大量的重复出现,造成大量的数据冗余。
2.更新异常
更新某些信息时,可能需要修改多条记录,增加了出错的风险
如果调整其中的一个数据,那么就需要更新所有的记录在MySQL中,如果有些更新成功,有些失败,就会造成数据不一致。
如果要将学分调成为100,就需要对MySQL中的所有数据进行更新,如果某些失败,就会造成数据不一致。
3.删除异常
删除某些记录时,可能会丢失重要信息
删除了所有选修"数学"课程的学生,课程名称
和 课程ID
的对应关系也会被丢失,无法得知课程ID 11
是"数学"。
4.插入异常
由于数据的部分依赖,可能无法插入某些信息
如果一个新课程尚未分配给任何学生,我们无法在当前表中直接插入它,因为需要同时提供一个学生ID,这与逻辑不符。
第三范式
满足第二范式的前提下,表中的非主属性必须直接依赖于主键,而不能依赖于其他非主属性。也就是说,表中的非主属性不应该存在传递依赖。
要求:消除传递依赖,即非主属性不能依赖于其他非主属性。
举例(描述学生就读于哪个学院)
错误形式:
学生表
学号 姓名 年龄 所在学院 学院地址 学院的电话
在这个表中,姓名和年龄与学号是强相关的,学院地址和学院的电话与所在学院是强相关的,可以看出,出现了两种强相关关系。
强相关关系中存在传递现象
学号--->所在学院--->学院电话,学院的地址
这样的关系我们称为依赖传递,不满足第三范式
正确形式:
学院表
学院编号 学院名 学院的地址 学院的电话
学生表
学号 姓名 年龄 学院的编号(外键)
这两张表都依赖于自己的主键,学生表可以通过外键建立各种的关系
第三范式可以解决数据冗余,更新异常,插入异常,删除异常等问题。
表的设计方式
一对一
一对一关系是指实体 A 的每条记录与实体 B 的一条记录唯一对应。
例如:一个用户只能有一个对应的用户详情。
设计表的方式
登陆系统
1.把两个实体的信息统计到一个表中
2.将两个实体信息分别写入两个表中,建立外键联系。
一对多
一对多关系是指实体 A 的一条记录可以对应实体 B 的多条记录,但实体 B 的每条记录只能对应实体 A 的一条记录。
实例:班级对学生
设计表的方式
将学生表与班级表建立关系
多对多
多对多关系是指实体 A 的一条记录可以对应实体 B 的多条记录,同时实体 B 的一条记录也可以对应实体 A 的多条记录。
实例:一个学生选修多门课程,一门课程被多个学生选修。
设计表的方式
分别对课程和学生建表,然后再建一个关系表创建关联的关系
代码演示
create table class(
->class_id bigint primary key auto_increment,
-> name varchar(12) not null
-> );
create table student(
-> student_id bigint primary key auto_increment,
-> name varchar(15) not null,
-> sn varchar(10) unique,
-> email varchar(20),
-> class_id bigint,
-> foreign key(class_id) references class(class_id)
-> );
create table course(
-> course_id bigint primary key auto_increment,
-> name varchar(20) not null
-> );
create table score(
-> score_id bigint primary key auto_increment,
-> student_id bigint,
-> course_id bigint,
-> score decimal(5,2),
-> foreign key(student_id) references student(student_id),
-> foreign key(course_id) references course(course_id)
-> );
注:班级表和学生表是一对一的关系,学生表和课程表之间是多对多的关系
希望能对大家有所帮助!!!!!