news 2026/4/23 11:31:29

一站式了解数据库三大范式(库表设计基础)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一站式了解数据库三大范式(库表设计基础)

文章目录

  • 引言
  • 第一范式
  • 第二范式
  • 第三范式
  • 总结❤️

引言

作为后端开发者,项目初期进行库表设计的时候,如果光凭经验而没有一套合适的方法论,大概率项目最后会变成一个难以维护的“史山”。那么我们就来简单讲讲数据库表设计的三大范式,尽量都让大家听懂,我们的最终目的是大家掌握应对各种业务场景设计的思维框架

第一范式

第一范式:确保关系中的所有属性(列)都是不可再分的原子性值。

具体含义:

  • 表中的每一个字段都不可再分。
  • 不允许在同一列中存储多个值,例如,一个“联系方式”字段不能包含“电话号码, 电子邮件地址”
  • 不允许在表中创建“重复组”——即一个记录(行)中不能有多个重复的字段,例如“产品1, 产品2, 产品3”

举个例子来回答,不允许在同一列中存储多个值:比如说地址这个列,你不能存储成广东省广州市xx区xx街道…这样整个字符串,这样地址还可以再进行拆分,而是你要拆成直到不能再进行拆分的原子字段,比如省,市,区等等。

一个记录(行)中不能有多个重复的字段,比如说课程里面你不能同时记录数学,语文等等,而是应该分开多个行进行记录

第二范式

第二范式:要求每一列(非主键字段)都完全依赖于主键

具体含义:

  • 如果一个表的主键是联合主键(由多个列组成),那么所有非主键列都必须依赖于整个联合主键。
  • 如果任何一个非主键列只依赖于联合主键中的部分列,则违反了 2NF。这会导致“部分函数依赖”。

举个例子来解释第二范式,订单表里面就不能出现商品的库存信息,因为商品的库存信息依赖于商品的ID而不依赖于订单ID。那么简单来说就是表里面的每个列都必须完全依赖于主键,不管这个主键是联合主键还是独立主键,不能出现部分依赖的情况,否则就要拆分部分依赖的列到其他表里面去。

再举个违反 2NF 的例子:(假设订单ID产品ID组成联合主键)

订单ID产品ID订单日期产品名称产品价格
1001A1012025-12-15笔记本电脑8000
1001B2052025-12-15鼠标150
1002A1012025-12-16笔记本电脑8000

问题:产品名称产品价格只依赖于产品ID(主键的一部分),与订单ID无关。这就是部分函数依赖

第三范式

第三范式:每一列都必须直接依赖于主键而不能间接依赖主键,即不能存在依赖传递。换句话说,任何非主键属性不能依赖于其他非主键属性。

具体含义:

  • 消除传递函数依赖。即如果A → B A \rightarrow BABB → C B \rightarrow CBC(其中A AA是主键),那么C CCA AA就是传递依赖,需要消除

举个例子来解释第三范式:订单表里面有用户ID,就不应该还冗余一列用户的注册时间。因为用户的注册时间依赖于用户ID(在订单表里面是非主键,在用户表里面是主键),所以用户的注册时间如果存在于订单表,就是有间接依赖,即依赖传递的情况。

再举个违反 3NF 的例子:(假设客户ID是主键)

客户ID客户姓名所在城市城市邮编
C001张三上海200000
C002李四上海200000
C003王五北京100000

问题:城市邮编依赖于所在城市,而所在城市依赖于客户ID客户 I D → 所在城市 → 城市邮编 客户ID \rightarrow 所在城市 \rightarrow 城市邮编客户ID所在城市城市邮编这就是传递函数依赖。每次有新的上海客户加入,城市邮编都会重复存储。

总结❤️

在实际的数据库设计中,通常会努力达到 3NF。然而,有时为了提高查询性能,可能会故意违反 3NF,采用反范式设计。为业务做出的妥协是可以理解的

我推荐大家可以利用DDD领域驱动设计的维度去结合三大范式来进行库表设计,比如在订单领域,地址就可以是订单表的列,可以冗余。在用户领域,地址就应该是一个实体,可以进行增删改查和独立的业务意义,有完整的生命周期。简单来说,就是在用户领域,地址应该被设置成一个单独ID的表,而在订单领域,地址只是一个值对象(无生命周期,下单即固化,类似于快照)

什么该冗余,什么不该冗余,有了一个切合实际的思维框架,而不是依赖于"经验"之谈,对项目的可维护性会有很大帮助

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:31:00

【流体】基于二维稳态不可压缩层流通道流(利用FVM和SIMPLE 解平行板间层流的速度、压力和温度)附Matlab代码和报告

✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 🍎 往期回顾关注个人主页:Matlab科研工作室 🍊个人信条:格物致知,完整Matlab代码获取及仿…

作者头像 李华
网站建设 2026/4/16 21:43:41

rh850 can uds刷写 boot +OTA 1. 基于can 通讯 的bootloader

rh850 can uds刷写 boot OTA 1. 基于can 通讯 的bootloader,芯片用的是rh850u2a16 2. 配套capl上位机 3. uds服务刷写 4. flash driver 可选择在ram中运行 5. 支持single map/ double map ota/single map GCFU ota三种模式下的刷写,支持单/双map 两种模式…

作者头像 李华
网站建设 2026/4/23 9:52:04

基于Matlab的遗传算法设计:多旅行商问题(MTSP)的求解与输出路径

基于matlab多旅行商MTSP问题,利用遗传算法求解多旅行商问题的算法设计,输出MTSP路径。 相互独立路径,同一起点路径。 程序已调通,可直接运行。直接上干货!咱们今天用Matlab整一个多旅行商问题的遗传算法解决方案。这个…

作者头像 李华
网站建设 2026/4/23 11:20:02

学了四年金融,想转AI:第一步究竟该迈向哪里?

临近毕业,当身边的同学纷纷锁定银行、券商和会计师事务所的职位时,金融系的陈琳却陷入了深深的迷茫。她看着自己写满宏微观经济学、货币银行学笔记的本子,再望向招聘网站上那些充满吸引力的“AI量化分析师”、“智能风控工程师”岗位&#xf…

作者头像 李华
网站建设 2026/4/23 11:18:42

接口测试的常见问题与解决方案

接口测试作为软件测试的关键环节,是确保系统组件间通信和数据交换正确性的重要手段。随着微服务架构和分布式系统的普及,接口测试在软件质量保障体系中的地位日益凸显。本文将系统梳理接口测试实践中常见的技术难点与典型问题,并提供经过验证…

作者头像 李华
网站建设 2026/3/14 6:34:42

需求可测试性分析Checklist:提升软件测试效率的实用指南

在软件测试领域,需求可测试性直接影响测试活动的成败。可测试性需求指需求描述是否具备可验证、可度量、无歧义等特性,确保测试团队能据此设计有效用例。本文基于行业实践,构建一份系统化的checklist,帮助测试从业者在需求评审阶段…

作者头像 李华