说一说数据库三大范式

本文详细解析了数据库设计中的三大范式——第一范式、第二范式和第三范式,通过实例阐述了各范式的含义、要求以及如何满足它们。讨论了满足范式的优缺点,强调在实际应用中应根据需求平衡数据冗余、更新和查询效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 第一范式(每列原子性)

第一范式要求所有的域都是原子性的,即每一列都不可(不须)分割。
以学生表为例,学生表有姓名、学号、年龄、性别、家庭住址等信息组成。在这个表中,可以看作所有列都不可分割(假设地址中的省、市、区、详细地址在本应用中是组合在一起的,不会拆分开来用。从这一点来看,地址列不可/不须分割),所以是满足第一范式的。
在这里插入图片描述
第一范式的合理性也需要结合实际需求来,上表满足第一范式是有一个前提条件,就是地址中的省、市、区、详细地址在本应用中是组合在一起的,不会拆分开来用。 假设本应用中需要把省、市、区、详细地址拆分开来使用,比如统计某省、某市、某区有多少学生,从而安排合适的校车接送。那上述设计就不满足数据库的第一范式了。此时就需要把地址拆分开来,才满足第一范式。
在这里插入图片描述
每列是否满足原子性是根据当前应用来判断的,并不是绝对的,就像本例中的地址一样。甚至是姓名在不同的应用中也可以说它满足满足或不满足原子性(假设需要把姓和名拆开…),所以在实际项目中一定要灵活处理。

2. 第二范式(要有主键,且实体属性完全依赖主键)

第二范式首先要求数据表必须要有主键,可以是单列构成的主键也可以是多列组合构成的主键。满足第二范式的表一定要先满足第一范式。
为什么要有主键?
因为要确保这一行数据的唯一性,因为主键本身的唯一性,就保证了这一行数据的唯一性,这样才能定位到这行数据。就像学生信息表,学号便可以当作主键来用,因为学号一定唯一。而姓名不可,因为可能会有重名,重复了就没有唯一性了。
实体属性完全依赖主键是什么意思?
是指每一列都和主键相关,并且不能只与主键的某一部分相关(主要针对联合主键)。

2.1 非联合主键情况

就像上面的学生信息表,主键number = 2020010223就已经决定了当前这一列归学号为2020010223的小明同学所有。这一列只能存放小明的年龄、性别、家庭住址等信息,而不能把小红的年龄、性别、家庭住址存放到这一列。如果把小红的年龄、性别、家庭住址存放到这一列,那这些属性就和主键没有任何关系了。

接下来再举个稍微复杂点的例子。
在这里插入图片描述
这张表里的班级名、语文老师名、英语老师名依赖小明吗?
不依赖!!!即使没有小明这个学生,也依然有高二三班,一个叫李明的语文老师和一个叫托尼的英语老师。所以说上述设计不满足数据库设计的第二范式。可以按照以下方式将上表更改成满足第二范式的 :
将班级信息单独抽取出来放到一张表中,在原来的学生信息表中新添加班级id列,作为外键。

学生信息表:
在这里插入图片描述
班级表:
在这里插入图片描述
这样一来就满足数据库设计第二范式了。

接下来我们再看点更复杂的。

2.2 联合主键情况

在前面我们还提到了一点:不能只与主键的某一部分相关(主要针对联合主键),这是怎么回事呢?一起来看一下吧!

假设有一张订单表是这样的:
在这里插入图片描述
这张表的主键是由order_id和book_id联合组成的。

mysql> show create table orders;
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                                                                                                                                                                             |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| orders | CREATE TABLE `orders` (
  `order_id` int(11) NOT NULL,
  `book_id` int(11) NOT NULL,
  `book_name` varchar(128) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值