1NF:数据表中的每一列信息都能够确切表述,但凡关系型数据库(mysql/oracle/sysbase/db2/sql server)都自动满足1N
表student1
id | name | age |
1 | 张三 | 12 |
2 | 李四 | 20 |
2NF:每个表的记录是唯一的,通常使用自增长主键实现
3NF:表中不存在冗余数据
表student2
id | name | age | 系别 | 专业 |
1 | 张三 | 12 | 计算机 | 软件工程 |
2 | 李四 | 20 | 计算机 | 软件工程 |
见表student2中红色部分,两条记录中系别和专业的数据有冗余
要改进设计则将系别和专业部分保存在另外一张(比如class),student2使用一个字段(classid)来关联class表
表student2
id | name | age | classid |
1 | 张三 | 12 | 1 |
2 | 李四 | 20 | 1 |
表class
id | 系别 | 专业 |
1 | 计算机 | 软件工程 |
2 | 英语系 | 商务英语 |
以上两张表通过表class的id和表student2的classid建立链接,在SQL语句中通过join关联:
select a.*,b.* from student2 a left join class b on a.classid=b.id
并不是所有情况下都需要符合3NF,为了提高效率,允许存在一些冗余数据,见下
分类表:category
id | name(分类名称) |
1 | 计算机 |
2 | 英语 |
分类表:books
id | catid | name(书名称) | count(书籍数量) |
1 | 1 | php开发 | 30 |
2 | 1 | java开发 | 32 |
按照以上设计,如要统计每个分类下书籍的总数量,则程序需要遍历每个分类且根据分类ID来统计书籍总数,在数据量较大的情况下,可能会影响性能。
可以这样优化,在category表中添加一个字段来保存该分类下所有书籍的总数
分类表:category
id | name(分类名称) | count(书籍数量) |
1 | 计算机 | 62 |
2 | 英语 | 0 |
分类表:books
id | catid | name(书名称) | count(书籍数量) |
1 | 1 | php开发 | 30 |
2 | 1 | java开发 | 32 |
如需查询某个分类下的书籍总数,只需要查category表即可,不需要统计books表中的数据
在此情况下,允许出现适当的数据冗余