数据库的三大范式(原理 + 例子详解)

上周,我那个朋友在讲数据库设计的时候,提到了三大范式。
第一范式,简单说就是每列都只能有原子数据,不能有复合数据。
比如,价格一栏不能同时写单价和折后价,得分开。

2 02 3 年,我在网上看到一个例子,有个表里的价格栏就犯了这个错误。
后来,他们把价格栏拆成了单价和折后价两栏,这样就符合第一范式了。

我那个朋友还提到,第二范式是在第一范式的基础上,要求所有非主键列都只能依赖于主键。
比如说,一个订单表,如果主键是订单号,产品名称和单价就不能直接依赖于订单号,得另开一个表。

还有第三范式,这是在第二范式的基础上,要求非主键列不能依赖于其他非主键列。
比如,用户名称不能通过订单号间接依赖于用户ID,用户信息应该单独一个表。

我有个疑问,就是有时候这些规则挺严格的,实际操作中是不是得灵活一点呢?我那个朋友说,对啊,得根据具体情况来。
不过,遵循这些原则确实能提高数据的质量和效率。
你看着办吧,这些规则挺复杂的。

【数据库基础】详解数据库第一范式、第二范式和第三范式

第一范式:数据不可分,列都是原子的,避免重复列。
简单说,就是数据不能拆分,每列都是最基本的单位。

第二范式:在第一范式的基础上,非主属性完全依赖于主键。
就是非主键数据只能由主键决定,不能由主键的一部分决定。

第三范式:在第二范式的基础上,非主属性不依赖于其他非主属性。
就是避免一个非主属性通过另一个非主属性间接依赖于主键。

总结:这三范式都是为了减少数据冗余,提高数据独立性。
用得越多,数据越干净,但设计也更复杂。
具体用哪个,看你的需求和数据情况。

第三范式举例说明

我曾在一家小公司做数据库管理员,有一次,我们公司新接了一个项目,要做的是一个在线书店的数据库。
项目初期,我们设计了一个“订单表”,里面记录了用户的订单信息,包括订单号、用户ID、商品ID、数量、价格等。
当时,我觉得这个表设计得很合理,因为订单号是主键,用户ID和商品ID是外键,价格是根据数量和商品价格计算得出的。

结果,上线后问题来了。
用户反馈说,当订单数量发生变化时,订单表中的价格也会跟着变,导致订单价格出现错误。
我一看,果然如此。
原来,我们在设计时没有考虑到第三范式的要求,价格实际上依赖于数量和商品价格,而商品价格又是依赖于商品ID的。
这样一来,价格就存在传递依赖,违反了第三范式。

于是,我赶紧修改了设计,将价格从订单表中分离出来,只保留计算价格的公式。
这样,当订单数量变化时,价格就不会发生变化了。
虽然这次修改让我的工作多了一些,但客户满意度提升了,数据库的稳定性也得到了保障。

等等,还有个事,我突然想到,如果有一天,商品价格调整了,我们还需要手动修改订单表中的价格,这样太麻烦了。
看来,我还可以在设计中加入更多的优化,比如将商品价格和用户折扣等数据单独存储,以进一步减少数据冗余和提高效率。
不过,这也意味着数据库设计会更复杂,需要权衡利弊。