# 数据库设计三范式

什么是数据库设计范式?
数据库表的设计依据。

# 第一范式

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

案例:
学生编号    学生姓名    联系方式
1001        张三        zs@gmail.com,135999999
1002        李四        li@gmail.com,136999999
1003        王五        ww@gmail.com,137999999

以上表设计不满足第一范式--没有主键,联系方式可拆分

修改:
学生编号(pk)    学生姓名        邮箱                联系电话
1001            张三        zs@gmail.com       135999999
1002            李四        li@gmail.com       136999999
1003            王五        ww@gmail.com       137999999

# 第二范式

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

案例:
学生编号        学生姓名        教师编号        教师姓名
1001            张三            001             王老师
1002            李四            002             赵老师
1002            李四            002             王老师
1001            张三            001             赵老师

以上表设计不满足第一范式--没有主键

修改:
学生编号    +    教师编号(pk)        学生姓名          教师姓名
1001            001             张三               王老师
1002            002             李四               赵老师
1002            002             李四               王老师
1001            001             张三               赵老师

学生编号和教师编号连个字段做复合主键
以上修改完之后表不满足第二范式--非主键字段,产生部分依赖(学生和教师关系产生多对多关系)
    导致:数据冗余,空间浪费

修改:
学生编号    学生姓名
1001        张三
1002        李四

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

学生教师联合表
id(pk)      学生编号(fk)   教师编号(fk)
1            1001          001
2            1002          001
3            1001          002
4            1002          002

# 第三范式

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

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

以上表的设计满足第一范式--有主键
以上表的设计满足第二范式--主键是单一主键,不是复合主键,没有产生部分依赖(表中学生和班级是一对多关系)

以上表不满足第三范式--传递性依赖(班级名称依赖班级编号,产生了传递依赖,不符合第三范式,产生了数据冗余)

修改:
班级表
班级编号(pk)      班级名称
01                  一班
02                  二班
...

学生表
学生编号(pk)      学生姓名        班级编号
1001                张三            01
...

作用:避免数据冗余,空间的浪费

# 总结

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

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

一对一:
    在一对一中,可能存在表字段太多,太庞大,需要拆分表
    
    案例:
    id      login_name      login_pwd       real_name       email
    1           admin       admin           张三            zs@gmail.com


    修改:
    登录信息表:
    id      login_name      login_pwd
    1       admin           admin

    用户详细信息表:
    id      real_name       email           login_id(fk+unique)
    100        admin        zs@gmail.com        1

    在一对一拆分表时,可以使用 外键+唯一性约束 设计表

# 重点

数据库设计三范式是理论上的。
实践和理论有时候有偏差。
最终的目的都是为了满足客户的需求,有的时候会拿数据冗余换速度。因为Sql中,表和表之间的连接次数过多,效率越低(笛卡尔积)
有的时候可能会存在冗余,但是为了减少表的连接次数,这样做也是合理的。