数据库设计三范式

简介: 第一范式要求字段原子性,不可再分;第二范式消除部分依赖,主键确定所有非主键;第三范式消除传递依赖。三者旨在减少数据冗余、提升维护效率,但实际设计需结合业务权衡,不必拘泥范式。

第一范式 - 1NF
遵循原子性。即,表中字段的数据,不可以再拆分。先看一个不符合第一范式的表结构,如下:
员工编码 姓名 年龄
001 销售部小张 28
002 运营部小黄 25
003 技术部小高 22
在这一个表中的,姓名 字段下的数据是可以再进行拆分的,因此它不符合第一范式,那怎么样才符合第一范式呢?如下:
员工编码 部门 姓名 年龄
001 销售部 小张 28
002 运营部 小黄 25
003 技术部 小高 22
那是否遵循第一范式就一定是好的呢?如下:
员工编码 姓名 地址
001 小张 江西省南昌市东湖区
002 小黄 广东省佛山市禅城区
003 小高 湖北省武汉市新洲区
通过观察上述表结构,我们发现,地址是可以再进一步拆分的,比如:
员工编码 姓名 省 市 区
001 小张 江西省 南昌市 东湖区
002 小黄 广东省 佛山市 禅城区
003 小高 湖北省 武汉市 新洲区
虽然拆分后,看上去更符合第一范式了,但是如果项目就只需要我们输出一个完整地址呢?那明显是表在没拆分的时候会更好用。所以范式只是给了我们一个参考,我们更多的是要根据项目实际情况设计表结构。
第二范式 - 2NF
在满足第一范式的情况下,遵循唯一性,消除部分依赖。即,表中任意一个主键或任意一组联合主键,可以确定除该主键外的所有的非主键值。再通俗点讲就是,一个表只能描述一件事情。我们用一个经典案例进行解析。
学号 姓名 年龄 课程名称 成绩 学分
001 小张 28 语文 90 3
001 小张 28 数学 90 2
002 小黄 25 语文 90 3
002 小黄 25 语文 90 3
003 小高 22 数学 90 2
我们先分析一下表结构。

  1. 假设学号是表中的唯一主键,那由学号就可以确定姓名和年龄了,但是却不能确定课程名称和成绩。
  2. 假设课程名称是表中的唯一主键,那由课程名称就可以确定学分了,但是却不能确定姓名、年龄和成绩。
  3. 虽然通过学号和课程名称的联合主键,可以确定除联合主键外的所有的非主键值,但是基于上述两个假设,也不符合第二范式的要求。

那我们应该如何调整表结构,让它能复合第二范式的要求呢?
我们可以基于上述的三种主键的可能,拆分成 3 张表,保证一张表只描述一件事情。

  1. 学生表 - 学号做主键
    学号 姓名 年龄
    001 小张 28
    002 小黄 25
    003 小高 22
  2. 课程表 - 课程名称做主键
    课程名称 学分
    语文 3
    数学 2
  3. 成绩表 - 学号和课程名称做联合主键
    学号 课程名称 成绩
    001 语文 90
    001 数学 90
    002 语文 90
    002 语文 90
    003 数学 90
    这时候我们可能会想,为什么我们就要遵循第二范式呢?不遵循第二范式会造成什么样的后果呢?
  4. 造成整表的数据冗余。
    如学生表,可能我就只有2个学生,每个学生都有许多的信息,比如,年龄、性别、身高、住址......如果与课程信息放到同一张表中,可能每个学生有3门课程,那数据总条数就会变成6条了。但是通过拆分,学生表我们只需要存储 2 条学生信息,课程表只需要存储 3 条课程信息,成绩表就只需保留学号、课程名称和成绩字段。
  5. 更新数据不方便。
    假设,课程的学分发生了变更,那我们就需要把整表关于该课程的学分都要更新一次,但如果我们拆分出课程表,那我们就只需要把课程表中的课程信息更新就行。
  6. 插入数据不方便或产生异常。
    ① 假设主键是学号或课程名称,我们新增了某个课程,需要把数据插入到表中,这时,可能只有部分人有选修这门课程,那我们插入数据的时候还要规定给哪些人插入对应的课程信息,同时可能由于成绩还没有,我们需要对成绩置空,后续有成绩后还得重新更新一遍。
    ② 假设主键是学号和课程名称的联合主键。同样也是新增了某课程,但是暂时没有人选修这门课,缺少了学号主键字段数据,会导致课程信息无法插入。
    第三范式 - 3NF
    在满足第二范式的情况下,消除传递依赖。即,在任一主键都可以确定所有非主键字段值的情况下,不能存在某非主键字段 A 可以获取 某非主键字段 B。
    仍然用一个经典例子来解析
    学号 姓名 班级 班主任
    001 小黄 一年级(1)班 高老师
    这个表中,学号是主键,它可以唯一确定姓名、班级、班主任,符合了第二范式,但是在非主键字段中,我们也可以通过班级推导出该班级的班主任,所以它是不符合第三范式的。
    那怎么设计表结构,才是符合第三范式的呢?
  7. 学生表
    学号 姓名 班级
    001 小黄 一年级(1)班
  8. 班级表
    班级 班主任
    一年级(1)班 高老师
    通过把班级与班主任的映射关系另外做成一张映射表,我们就成功地消除了表中的传递依赖了。
    总结
    不知道读者们有没有发现,以上所介绍的范式的最终目的都是为了减少我们的工作量呢?所以说,尽管范式是一种很好的指导规范,但在实际应用中,我们也不需要太局限在范式中,更多的是应该从项目中出发,设计出合理的表结构。
    以下是本篇三范式的简单总结:
    ● 第一范式(1 NF):字段不可再拆分。
    ● 第二范式(2 NF):表中任意一个主键或任意一组联合主键,可以确定除该主键外的所有的非主键值。
    ● 第三范式(3 NF):在任一主键都可以确定所有非主键字段值的情况下,不能存在某非主键字段 A 可以获取 某非主键字段 B。
相关文章
|
12月前
|
弹性计算 网络协议 Linux
阿里云服务器ECS全解析:什么是ECS?实例规格族、付费类型、地域及网络可用区详细说明
阿里云ECS是安全可靠、弹性灵活的云服务器,支持多种实例规格与付费模式。本文详解ECS概念、实例类型、地域可用区、网络配置及购买流程,助您快速掌握创建与使用方法。
1668 0
|
10月前
|
运维 安全 Devops
生产环境缺陷管理
git-poison基于go-git实现分布式bug追溯,解决多分支开发中bug漏修、漏发等协同难题。通过“投毒-解毒-银针”机制,自动化卡点发布流程,降低沟通成本,避免人为失误,已在大型团队落地一年,显著提升发布安全与效率。
|
10月前
|
SQL Java 数据库连接
持久层框架MyBatisPlus
MyBatisPlus是MyBatis的增强工具,简化单表CRUD操作,无需编写XML即可实现增删改查。通过继承BaseMapper、使用Wrapper条件构造器、分页插件等功能,大幅提升开发效率。支持自定义SQL、逻辑删除、枚举与JSON处理,并提供代码生成器和通用Service层封装,广泛应用于企业级项目中。
|
10月前
|
Java 测试技术 Linux
生产环境发布管理
本文介绍大型团队如何通过自动化部署平台实现多环境(dev/test/pre/prod)发布管理,涵盖各环境职责、基于Jenkins+K8S的CI/CD流程、分支可视化操作、容器化部署机制及日志排查方案,提升发布效率与系统稳定性。
|
10月前
|
XML JSON Java
什么是RESTful
RESTful是一种基于资源的API设计规范,主张用URI标识资源,HTTP动词操作资源,实现统一、标准的接口风格。它解决了传统接口路径混乱、行为不一致的问题,具有结构清晰、易于理解与扩展的优势,提升系统可维护性与团队协作效率。
|
10月前
|
前端开发 程序员 开发者
常见注解及使用说明
本文介绍了SpringMVC中@RequestMapping注解的作用,它用于将HTTP请求映射到控制器方法,实现前后端接口路径的对应。通过示例讲解了其在增删改查中的应用,并提及@GetMapping等派生注解为@RequestMapping的封装,帮助开发者快速构建Web接口。
|
10月前
|
JSON 缓存 前端开发
什么是跨域
CORS(跨域资源共享)是W3C标准,允许浏览器向跨源服务器发起XMLHttpRequest请求,突破AJAX同源限制。需浏览器和服务器共同支持,主流浏览器均已兼容。通信过程由浏览器自动完成,开发者无需特殊处理。请求分为简单和非简单两类,后者会先发送OPTIONS预检请求确认权限。服务器通过设置Access-Control-Allow-Origin等头部字段控制跨域访问。相比仅支持GET的JSONP,CORS支持所有HTTP方法,更灵活安全。
|
10月前
|
敏捷开发 Dubbo Java
需求开发人日评估
本文介绍敏捷开发中工时评估的关键——人日估算方法,涵盖开发、自测、联调、测试及发布各阶段周期参考,并提供常见需求如增删改查、导入导出、跨服务调用等的典型人日参考,助力团队科学规划迭代。
|
10月前
|
SQL 安全 网络协议
常见的网络攻击
恶意软件指具有险恶意图的程序,如病毒、勒索软件、间谍软件等,常通过钓鱼邮件或漏洞入侵系统,窃取数据、破坏系统或加密文件勒索。网络钓鱼伪装成可信来源骗取敏感信息。中间人攻击则在通信中窃听或篡改数据。DDoS攻击利用大量流量瘫痪系统,近年呈高频、大体积趋势,常见于僵尸网络和L7层攻击。SQL注入通过输入恶意代码获取非法数据访问权限。零日攻击利用未修复漏洞发起突击。DNS隧道则滥用DNS协议传输隐蔽数据,用于数据外泄或远程控制。各类攻击日益复杂,需综合防御。
|
10月前
|
SQL 安全 关系型数据库
了解SQL注入
SQL注入是利用Web应用输入验证缺陷,将恶意SQL代码注入数据库查询的攻击方式。可导致身份绕过、数据泄露、篡改甚至系统命令执行。常见于登录框等用户输入场景,通过构造特殊字符如单引号、注释符改变SQL逻辑。防御需结合输入验证、参数化查询与错误信息管控,开发与运维协同防护。