hincky的主页 hincky的主页
  • 学习笔记

    • Vue笔记
    • Vuepress
    • nginx
  • 语言类

    • java
    • go
    • python
    • 设计模式
  • 框架类

    • Spring
    • Spring Security
    • Mybatis
  • 容器技术

    • docker
    • k8s
    • helm
    • prometheus
    • grafana
    • jenkins
  • 命令集合

    • linux命令
    • docker命令
    • git命令
    • vim命令
    • k8s命令
  • 数据库

    • sql
    • mysql
  • 协议

    • 网络模型
    • http/1.1
    • WebSocket
    • http/2
    • TLS/SSL
    • tcp
    • IP
    • tcpdump抓包命令
    • wireshark抓包工具
  • 通用

    • Git
  • 技术分享

    • git push/pull总是超时怎么办
    • idea debug技巧
    • postman使用
    • 问题总结
    • idea使用技巧
  • Oauth2

    • Oauth2原理
  • 项目列表

    • redis项目
    • 微服务项目
  • 分类
  • 标签
  • 归档
  • 随笔
GitHub (opens new window)

Hincky

当有趣的人,做想做的事
  • 学习笔记

    • Vue笔记
    • Vuepress
    • nginx
  • 语言类

    • java
    • go
    • python
    • 设计模式
  • 框架类

    • Spring
    • Spring Security
    • Mybatis
  • 容器技术

    • docker
    • k8s
    • helm
    • prometheus
    • grafana
    • jenkins
  • 命令集合

    • linux命令
    • docker命令
    • git命令
    • vim命令
    • k8s命令
  • 数据库

    • sql
    • mysql
  • 协议

    • 网络模型
    • http/1.1
    • WebSocket
    • http/2
    • TLS/SSL
    • tcp
    • IP
    • tcpdump抓包命令
    • wireshark抓包工具
  • 通用

    • Git
  • 技术分享

    • git push/pull总是超时怎么办
    • idea debug技巧
    • postman使用
    • 问题总结
    • idea使用技巧
  • Oauth2

    • Oauth2原理
  • 项目列表

    • redis项目
    • 微服务项目
  • 分类
  • 标签
  • 归档
  • 随笔
GitHub (opens new window)
  • 数据库

    • sql

    • MySQL开发规范

    • mysql

      • 数据库三范式
        • 1NF
        • 2NF
          • eg1
          • eg2
        • 3NF
          • eg1
          • eg2
        • 总结
      • 查询语句如何执行
        • 连接器
          • 连接问题
        • 查询缓存
        • 分析器
          • 词法分析
          • 语法分析
        • 优化器
        • 执行器
      • 更新语句如何执行
        • redo log
          • crash-safe
          • redo log特点
        • binlog
          • 数据恢复过程
          • 两段提交
          • 先redo后bin
          • 先bin后redo
          • binlog特点
        • 总结
          • 预防mysql异常重启
          • 如何选择备份周期
      • 事务隔离
        • 隔离级别
          • 读提交 和 可重复读
          • 不同隔离级别 视图创建差异
          • Oracle迁移事项
          • 可重复度的场景
        • 事务隔离的实现
          • 如何避免长事务
        • 事务启动方式
      • 索引入门
        • 常见索引模型
          • 哈希KV表
          • 有序数组
          • 搜索树
          • 数据库常用N叉树
        • InnoDB索引模型-B+树
          • 主键索引和普通索引区别
    • MySQL调优

    • kafka

  • 网络协议以及抓包工具

  • Git笔记

  • 技术分享

  • Oauth2

  • 计算机相关技术
  • 数据库
  • mysql
hincky
2022-11-11
目录

数据库三范式

范式(NF)

序数大的范式首先满足前面序数小的范式要求

# 1NF

强调列的原子性,即列不能够再分成其他几列。

考虑这样一个表:【联系人】(姓名,性别,电话)

如果在实际场景中,一个联系人有家庭电话和公司电话,那么这种表结构设计就没有达到 1NF。要符合 1NF 我们只需把列(电话)拆分,即:【联系人】(姓名,性别,家庭电话,公司电话)。1NF 很好辨别,但是 2NF 和 3NF 就容易搞混淆。

# 2NF

首先是 1NF,另外包含两部分内容:

  • 一是表必须有一个主键;
  • 二是没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。

# eg1

因为我们知道在一个订单中可以订购多种产品,所以单单一个 OrderID 是不足以成为主键的,主键应该是(OrderID,ProductID)。显而易见 Discount(折扣),Quantity(数量)完全依赖(取决)于主键(OderID,ProductID),而 UnitPrice,ProductName 只依赖于 ProductID。所以 OrderDetail 表不符合 2NF。不符合 2NF 的设计容易产生冗余数据。

可以把【OrderDetail】表拆分为【OrderDetail】(OrderID,ProductID,Discount,Quantity)和【Product】(ProductID,UnitPrice,ProductName)来消除原订单表中UnitPrice,ProductName多次重复的情况。

# eg2

假定选课关系表:student_course:student_no,student_name,age,course_name,grade,credit 其中主键为(student_no,course_name)

但是学分credit完全依赖于课程名称,学生姓名年龄完全依赖学号,不符合2NF

所以要拆解为:

student:student_no,student_name,age

course:course_name,credit

student_course:student_no,course_name,grade

# 3NF

首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。

# eg1

考虑一个订单表【Order】(OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主键是(OrderID)。

其中 OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity 等非主键列都完全依赖于主键(OrderID),所以符合 2NF。不过问题是 CustomerName,CustomerAddr,CustomerCity 直接依赖的是 CustomerID(非主键列),而不是直接依赖于主键,它是通过传递才依赖于主键,所以不符合 3NF。

通过拆分【Order】为【Order】(OrderID,OrderDate,CustomerID)和【Customer】(CustomerID,CustomerName,CustomerAddr,CustomerCity)从而达到 3NF。

# eg2

假定学生关系表:student:student_no,student_name,age,academy_id(学院电话),academy_telephone

其中学院id依赖于学号;学院地址和学院电话依赖于学院id。有传递关系,不符合3NF

所以应该拆解为:

student:student_no,student_name,age,academy_id

academy:academy_id(学院电话),academy_telephone

# 总结

第二范式(2NF)和第三范式(3NF)的概念很容易混淆,区分它们的关键点在于:

2NF:非主键列是否完全依赖于主键,还是依赖于主键的一部分;完全依赖主键符合2NF

3NF:非主键列是直接依赖于主键,还是直接依赖于非主键列。 直接依赖主键符合3NF

编辑 (opens new window)
#mysql
简版开发规范
查询语句如何执行

← 简版开发规范 查询语句如何执行→

最近更新
01
人生前期重要的能力
05-17
02
防火墙命令
04-11
03
docker-compose部署mysql主从集群
03-22
更多文章>
Theme by Vdoing | Copyright © 2022-2023 Hincky | MIT License | 粤ICP备2022120427号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式