数据库三范式


数据库三范式

设计表的依据。按照这个三范式设计的表不会出现数据冗余和空间浪费。

数据库三范式:

  1. 第一范式:任何一张表都应该有主键,并且每一个字段原子性不可再分。
  2. 第二范式:建立在第一范式的基础之上,所有非主键字段完全依赖主键,不能产生部分依赖。
  3. 第三范式:建立在第二范式的基础之上,所有非主键字段直接依赖主键,不能产生传递依赖。

详细解释

1、第一范式:任何一张表都应该有主键,并且每一个字段原子性不可再分

第一范式:

​ 第一范式最核心,最重要的范式,所有表的设计都要满足!

​ 必须要有主键,并且每一个字段的原子性不可再分!

例:``student`表

学生编号学生姓名联系方式
1001张三zhangshan.com,10086
1002李四lisi.com,1008611
1001王五wangwu.com,1008612

上表不满足第一范式:

  • 没有主键(学生编号存在重复)
  • 联系方式字段不满足原子性不可再分(可以再分为 邮箱和电话号码)

修改为满足第一范式的表:

学生编号(pk)学生姓名邮箱电话
1001张三zhangsna.com10086
1002李四lisi.com1008611
1003王五wangwu.com1008612

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

第二范式:

  • 满足第一范式
  • 非主键字段完全依赖主键,不能产生部份依赖

例如:

学生编号学生姓名教师编号教师姓名
1001张三001王老师
1002李四002李老师
1003王五001王老师
1001张三002李老师

分析上表是否满足第一范式?

-------- 不满足,(没有主键)

怎么满足第一范式? 修改:

学生编号 + 教师编号(pk 复合主键)学生姓名教师姓名
1001 001张三王老师
1002 002李四李老师
1003 001王五王老师
1001 002张三李老师

学生编号、教师编号这两个字段做符合主键,经过修改后上表满足了第一范式,但是满足第二范式嘛?

-------- 不满足:1001--> 张三001--> 王老师(张三依赖于001、王老师依赖于001),显然非主键字段产生了对主键的部份依赖!

产生部份依赖有什么缺点:数据冗余、空间浪费。(张三重复了,王老师重复了!)


为了满足第二范式,你必须这样设计:

学生和教师是多对多的关系!!!!!

student表:

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

teacher表:

教师编号(pk)教师姓名
001王老师
002李老师

s_t表(学生教师关系表):

id(pk)学生编号(fk)教师编号(fk)
11001001
21001002
31002002
41003001

口诀:多对多怎么设计?

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

3、第三范式:建立在第二范式的基础之上,所有非主键字段直接依赖主键,不能产生传递依赖

第三范式:

  • 满足第二范式
  • 所有非主键字段直接依赖主键,不能产生传递依赖。

例如:学生班级表

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

上表是否满足第二范式?

--------------满足


是否满足第三范式?

-------------不满足:1001 ---> 张三1001 ---> 01,那么1001 --- > 01产生了传递依赖,不符合三范式的要求。产生了数据的冗余(三班重复了)

优化:班级和学生是一对多的关系!

怎么设计一对多?

class班级表:

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

studet表():

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

一对多建表口诀:

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

数据库表的设计总结

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

多对多:多对多,三张表,关系表两外键

一对一:一对一,外键唯一

一对一

一对一放到一张表不就行了吗?还要拆分?

在实际开发中,可能一张表的字段太多了,太过于庞大,这个时候需要拆表:

没有拆表前:一张表

user表:

id login_name login_pwd realname gender email phone address …

--------------------------------------------------------------

1 张三 123 …

2 李四 456 …

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

user_login登录信息表:

id(pk) login_name login_pwd

--------------------------------

1 张三 123

2 李四 456

user_detail用户信息表:

id(pk) realname gender email phone address … login_id(fk + unique)

-------------------------------------------------------------

001 张三 … 1

002 李四… 2

问题来了,一张表拆分为两张表,怎么保证为是一对一

  • 一种方案是:共享主键(同主键)—— 用的少
  • 常用方案:设置唯一外键(fk + unique)

口诀:一对一表拆分

一对一,外键唯一

表设计以满足客户需求为准

注意:数据库三范式是理论上的。实际和理论是有偏差的。

最终目的是为了满足用户的需求,有的时候会拿冗余来换取速度。

因为在执行sql语句时,表和表之间的连接次数越多,查询效率越慢(笛卡尔积)

有的时候会存在冗余,但为了减少连接的次数,这样做也是合理的。(就比如上述一对一的表拆分,其实一张表就可以了,只不过表字段多,但相比于拆分为两张表来说,它的查询效率是更高的!)

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值