1、概念
数据库表的设计依据。教你怎么进行数据库表的设计。
2、数据库设计范式
第一范式 | 要求任何一张表必须有主键,每一个字段原子性不可再分。 |
---|---|
第二范式 | 建立在第一范式的基础之上,要求所有非主键字段完全依赖主键,不要产生部分依赖。 |
第三范式 | 建立在第二范式的基础之上,要求所有非主键字段直接依赖主键,不要产生传递依赖。 |
声明:三范式是面试官经常问的,所以一定要熟记在心!
设计数据库表的时候,按照以上的范式进行,可以避免表中数据的冗余,空间的浪费。
3、第一范式
最核心,最重要的范式,所有表的设计都需要满足。<br /> 必须有主键,并且每一个字段都是原子性不可再分。
学生编号 学生姓名 联系方式<br /> ------------------------------------------<br /> 1001 张三 zs@gmail.com,1359999999<br /> 1002 李四 ls@gmail.com,13699999999<br /> 1001 王五 ww@163.net,13488888888
以上是学生表,满足第一范式吗?<br /> 不满足,第一:没有主键。第二:联系方式可以分为邮箱地址和电话<br /> <br /> 学生编号(pk) 学生姓名 邮箱地址 联系电话<br /> ----------------------------------------------------<br /> 1001 张三 zs@gmail.com 1359999999<br /> 1002 李四 ls@gmail.com 13699999999<br /> 1003 王五 ww@163.net 13488888888
4、第二范式:
建立在第一范式的基础之上,<br /> 要求所有非主键字段必须完全依赖主键,不要产生部分依赖。
学生编号 学生姓名 教师编号 教师姓名<br /> ----------------------------------------------------<br /> 1001 张三 001 王老师<br /> 1002 李四 002 赵老师<br /> 1003 王五 001 王老师<br /> 1001 张三 002 赵老师
这张表描述了学生和老师的关系:(1个学生可能有多个老师,1个老师有多个学生)<br /> 这是非常典型的:多对多关系!
分析以上的表是否满足第一范式?<br /> 不满足第一范式。<br /> <br /> 怎么满足第一范式呢?修改
学生编号+教师编号(pk) 学生姓名 教师姓名<br /> ----------------------------------------------------<br /> 1001 001 张三 王老师<br /> 1002 002 李四 赵老师<br /> 1003 001 王五 王老师<br /> 1001 002 张三 赵老师
学生编号 教师编号,两个字段联合做主键,复合主键(PK: 学生编号+教师编号)<br /> 经过修改之后,以上的表满足了第一范式。但是满足第二范式吗?<br /> 不满足,“张三”依赖1001,“王老师”依赖001,显然产生了部分依赖。<br /> 产生部分依赖有什么缺点?<br /> 数据冗余了。空间浪费了。“张三”重复了,“王老师”重复了。<br /> <br /> 为了让以上的表满足第二范式,你需要这样设计:<br /> 使用三张表来表示多对多的关系!!!!<br /> 学生表<br /> 学生编号(pk) 学生名字<br /> ------------------------------------<br /> 1001 张三<br /> 1002 李四<br /> 1003 王五<br /> <br /> 教师表<br /> 教师编号(pk) 教师姓名<br /> --------------------------------------<br /> 001 王老师<br /> 002 赵老师
学生教师关系表<br /> id(pk) 学生编号(fk) 教师编号(fk)<br /> ------------------------------------------------------<br /> 1 1001 001<br /> 2 1002 002<br /> 3 1003 001<br /> 4 1001 002<br />
背口诀:多对多怎么设计?
多对多,三张表,关系表两个外键!!!!!!!!!!!!!!!
5、第三范式
第三范式建立在第二范式的基础之上<br /> 要求所有非主键字典必须直接依赖主键,不要产生传递依赖。
学生编号(PK) 学生姓 班级编号 班级名称<br /> ---------------------------------------------------------<br /> 1001 张三 01 一年一班<br /> 1002 李四 02 一年二班<br /> 1003 王五 03 一年三班<br /> 1004 赵六 03 一年三班<br /> <br /> 以上表的设计是描述:班级和学生的关系。很显然是1对多关系!<br /> 一个教室中有多个学生。
分析以上表是否满足第一范式?<br /> 满足第一范式,有主键。<br /> <br /> 分析以上表是否满足第二范式?<br /> 满足第二范式,因为主键不是复合主键,没有产生部分依赖。主键是单一主键。<br /> <br /> 分析以上表是否满足第三范式?<br /> 第三范式要求:不要产生传递依赖!<br /> 一年一班依赖01,01依赖1001,产生了传递依赖。<br /> 不符合第三范式的要求。产生了数据的冗余。<br /> <br /> 那么应该怎么设计一对多呢?
班级表:一<br /> 班级编号(pk) 班级名称<br /> ----------------------------------------<br /> 01 一年一班<br /> 02 一年二班<br /> 03 一年三班
学生表:多
学生编号(PK) 学生姓名 班级编号(fk)<br /> -------------------------------------------<br /> 1001 张三 01 <br /> 1002 李四 02 <br /> 1003 王五 03 <br /> 1004 赵六 03 <br /> <br /> 背口诀:<br /> 一对多,两张表,多的表加外键!!!!!!!!!!!!
6、总结表的设计?
一对多:一对多,两张表,多的表加外键!!!!!!!!!!!!
多对多:多对多,三张表,关系表两个外键!!!!!!!!!!!!!!!
一对一:一对一,外键唯一!!!!!!!!!!<br /> 一对一放到一张表中不就行了吗?为啥还要拆分表?<br /> 在实际的开发中,可能存在一张表字段太多,太庞大。这个时候要拆分表。<br /> 一对一怎么设计?<br /> 没有拆分表之前:一张表<br /> t_user<br /> id login_name login_pwd real_name email address........<br /> ---------------------------------------------------------------------------<br /> 1 zhangsan 123 张三 zhangsan@xxx<br /> 2 lisi 123 李四 lisi@xxx<br /> ...<br /> <br /> 这种庞大的表建议拆分为两张:<br /> t_login 登录信息表<br /> id(pk) login_name login_pwd <br /> ---------------------------------<br /> 1 zhangsan 123 <br /> 2 lisi 123
t_user 用户详细信息表<br /> id(pk) real_name email address........ login_id(fk+unique)<br /> -----------------------------------------------------------------------------------------<br /> 100 张三 zhangsan@xxx 1<br /> 200 李四 lisi@xxx 2
口诀:一对一,外键唯一!!!!!!!!!!
7、嘱咐一句话:
数据库设计三范式是理论上的。
实践和理论有的时候有偏差。
最终的目的都是为了满足客户的需求,有的时候会拿冗余换执行速度。
因为在sql当中,表和表之间连接次数越多,效率越低。(笛卡尔积)
有的时候可能会存在冗余,但是为了减少表的连接次数,这样做也是合理的,<br /> 并且对于开发人员来说,sql语句的编写难度也会降低。
面试的时候把这句话说上:他就不会认为你是初级程序员了!