1-数据库三范式基本介绍

用 时间 换 空间

几亿。 数据量可能是几个T,但是你如果数据库设计的得当,这个储存量是可以减少,可能只有几百G

1000G=1T 硬盘产商计算。

操作系统计算 1024G=1T

很多东西

sql里面有一个概念叫 笛卡尔积。 n* n * n

第一张表里有100条数据,我只相查一条 。

那100遍。

分数=90分。

学生名字 分数
小名 12
小华 50
李华 60
李四 12

第一条开始, 假如说我要的数据在第50条,计算机认为你后面50条至100条可能还会有符合条件的数据。

我要查两个表,并且,我要用第一张表查到的数据,再去查第二张表。

n * n=n²

我一开始的数据,用一张表,储存很多数据,会造成数据的冗余,—>n

优化后,用多张表储存,避免了数据的冗余,但是我原来只需要查一张表,那我现在就要查多张表。 时间就变成了 n²

一、一览

第一范式:要求任何一张表必须有主键,每一个字段原子性不可再分。

第二范式:建立在第一范式的基础上,要求所有非主键字段完全依赖主键,不要产生部分依赖。

第三范式:建立在第二范式基础,要求所有非主键字段直接依赖主键,不要产生传递依赖。

避免数据的冗余,空间的浪费。

什么叫依赖:

如果确定一个表中的某个数据(A),则就可以确定该表中的其他另一个数据(B),则我们说:B依赖于A。

实际上,一个表只要有主键,则其他非主键一定是依赖于主键的。

什么叫“部分依赖”:

如果确定一个表中的某个数据组合(A,B),则就可以确定该表中的其他另一个数据(C),则我们说:C依赖于(A,B)(此时A,B通常就是做出主键)。

但:如果某个数据D,它只依赖于数据A,或者说,A一确定,则D也可以确定,此时我们就称为“数据D部分依赖于数据A——可见部分依赖是指某个非主键字段,依赖于联合主键字段的其中部分字段。

依赖—————> 一种关系

二、逐个分析

1、第一范式 (1NF):原子性(存储的数据应该具有“不可再分性”)

1必须有主键,且2.每个字段是原子性的不能再分。

不符合第一范式的示例

主键:主键是唯一的。可以为一个字段,也可以为多个字段一起组合成一个主键—>复合主键。

学生编号 学生姓名 联系方式

1001 张三 zs@gmail.com,1359999999

1002 李四 ls@gmail.com,13699999999

1001 王五 ww@163.net,13488888888

存在问题:

  • 最后一条记录和第一条重复(不唯一,没有主键)
  • 联系方式字段可以再分,不是原子性的

解决方案:

学生编号(pk) 学生姓名 email 联系电话

1001 张三 zs@gmail.com 1359999999

1002 李四 ls@gmail.com 13699999999

1003 王五 ww@163.net 13488888888

关于第一范式:

每一行必须唯一,也就是每个表必须有主键,这是我们数据库设计的最基本要求,主要通常采用数值 型或定长字符串表示,关于列不可再分,应该根据具体的情况来决定。如联系方式,为了开发上的便利可能就采用 一个字段了。

2、第二范式 唯一性 (消除非主键部分依赖联合主键中的部分字段)(一定要在第一范式已经满足的情况下)

二范式是建立在第一范式基础上的,另外要求所有非主键字段完全依赖主键,不能产生==部分依赖==。

1.学生和教师的表

示例:

这里涉及到一个关系 ==多对多==

学生编号 学生姓名 教师编号 教师姓名

1001 张三 001 王老师

1002 李四 002 赵老师

1003 王五 001 王老师

1001 张三 002 赵老师

1001 张三 003 陈老师

2个中文字符一个中文字符对应3个字节,1Byte=8bit

分析以上的表满足第一范式吗?不满足,没有主键

情况一

修改建议

确定主键: —>使用复合主键

学生编号 教师姓名 学生姓名 教师编号

1001王老师 张三 001

1002赵老师 李四 002

1003王老师 王五 001

1001赵老师 张三 002

情况二、

修改建议

确定主键: —>使用复合主键 依赖于一部分。

考虑—>数据冗余

原来的作用

这张表是要描述一个

学生 与老师的关系对应。

学生与老师的对应关系。

Final

假如

一、我想确定这个老师跟这个学生是否有关系?

我有学生的编号和教师的编号。

学生编号(PK) 教师编号(PK) 学生姓名 教师姓名

1001 001 张三 王老师

1002 002 李四 赵老师

1003 001 王五 王老师

1001 002 张三 赵老师

SQL例子。

SELECT stuName FROM test_table WHERE StuID=1001;

这张表描述了学生和老师的关系:一个学生可能有多个老师,一个老师有多个学生。

张三依赖1001 王老师依赖001 产生了部分依赖。

有什么缺点?数据冗余,空间浪费。大量的冗余

主要涉及到的冗余字段为“学生姓名”和“教师姓名”。

出现冗余的原因在于:

学生姓名部分依赖了主键的一个字段学生编号,而没有依赖教师编号,而教师姓名部门依赖了主键的一个 字段教师编号,这就是第二范式部分依赖。

学生姓名依赖于学生编号,老师名字依赖于教师编号,都是==主键的一部分==,——>部分依赖。

即==多对多的问题==

how ?

建立多张表

一个学生表、一个教师表、一个学生关系关系表。

学生信息表

学生编号 学生姓名
1001 张三
1002 李四
1003 王五

学生名字和一个教师名字

次数n1* n2* *n3 —> 时间复杂度的问题。

n1 用空间换时间。

SQL 有索引进制。

教师信息表

教师编号 教师姓名
001 王老师
002 赵老师
003 陈老师

教师学生关系表

id(fk) 学生编号(fk) –>学生表的学生编号 教师编号(PK) 教师编号(fk) –>教师表的教师编号
1 1001 001
2 1002 002
3 1001 003

多对多,三张表,关系表两个外键。

小练习

看另一个案例 student_course

student_number student_name course_name credit(课程代码)
100 小明 马克思 1aaa
102 小花 马克思 1aaa
100 小明 毛泽东思想 2bbbb

多对多,三张表,关系表两个外键。

3.第三范式 (独立性,消除传递依赖)

第三范式建立在第二范式的基础上。

​ 要求非主键字段必须直接依赖主键,不要产生传递依赖。

在一个具有主键的表中,假设主键为A,其必然其他非主键都依赖于该主键,比如:B依赖于A,C依赖于A,D依赖于A。。。。。。

但同时:如果该表中的某个字段B的值一确定,就能够确定另一个字段的值C,则我们称为C依赖于B。

那么,就出现了:

C依赖B,B依赖A——这就是传递依赖。

则消除该传递依赖的的通常做法,就是将C依赖于B的数据,分离到另一个表中。

学生班级对应表

一对多。一个班级可以包含多个学生,一个学生只能对应一个班级。

学生与班级。

学生编号 学生姓名 班级编号 班级名称
1001 张三 01 一年级一班
1002 李四 01 一年级一班
1003 王五 03 一年级三班
1004 03 一年级三班

一个教室中有多个学生。 —->一对多。

A1:符合第一范式吗?

​ Q:符合,只有一个外键。

A2:符合第二范式吗?

​ Q:没有部分依赖。符合

A3:符合第三范式吗?

​ Q:班级名称依赖于班级编号,班级编号依赖于学生编号—>存在==传递依赖==

解决方法

一对多,两张表,多的表加外键。

一、学生表

学生编号(pk) 学生姓名 班级编号(fk)
1001 张三 01
1002 李四 02
1003 王五 03
1004 老六 03

二、班级信息表

班级编号(pk) 班级名称
01 一年级一班
02 一年级二班
03 一年级三班

三、总结

学生与班级 ,

一对多:

​ 两张表,多的表加外键。

学生与课程。一个学生可能有多门课程,一门课程会有多个学生。

多对多:

​ 三张表,关系表两个外键。

一对一:

​ 一对一、拆分表,外键唯一!

​ 在实际开发中,可能存在一张表字段太多,太庞大,这个时候要拆分表。

一对一怎么设计?

没有查分表之前:一张表

id(pk) account password email realname address
1 zhangsang 123 1412842323491@qq.com 张三 广东省xxx
2 lisi 123 14128213291@qq.com 李四 广东省xxx

这种庞大的表建议拆分为两张:

t_login 登录表

id(pk) account password
1 1235 123
2 1234 123

t_user 用户信息表

id(pk) realname email address loginid(fk) unique –>以t_login表中的id为外键 account
1001 张三 1412842323491@qq.com 广东省 1 1235
1002 李四 14128213291@qq.com 广东省 2 1234

四、老杜一些嘱咐的话

数据库设计尽量遵循三范式,但是还是根据实际情况进行取舍,有时可能会拿冗余换速度,最终用目的要满足客户需 求。

因为在 sql 当中,表和表之间链接次数越多,效率越低(笛卡尔积)

有的时候可能会存在冗余,但为了减少表的连接次数,这样子做也是合理的,并且对于开发人员来说,sql 语句的编写难度也会降低。