Mysql学习之路04-三大范式

本文详细介绍了数据库设计中的第一、第二和第三范式,通过实例说明如何避免数据冗余和更新异常等问题,探讨了反三范式的应用场景。

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

第一范式
原子性。表的元组不可再拆分成更小的元组。
第二范式
非主键必须完全依赖主键,而不是仅仅依赖主键的一部分。
举个例子,美国销售军火的时候,对每一样武器,根据国家或地区的不同而给出不同的价格。建个表看看:

CREATE TABLE weapon_price  
(  
    wp_id UNSIGNED INT NOT NULL AUTO_INCREMENT, -- 武器编号  
    cs_id UNSIGNED INT NOT NULL , -- 消费者 id   
    wp_price UNSIGNED INT NOT NULL, -- 武器价格, 根据武器买主的不同而不同  
    cs_name VARCHAR(40) NOT NULL -- 消费者的称呼,例如 台湾/菲律宾/韩国  
);  

weapon_price 用于描述武器的价格,价格根据(武器,消费者)的不同而不同。对于此表 (wp_id,cs_id) 是其主键。其中 wp_price 是完全依赖于 (wp_id,cs_id) 的,而 cs_name 则只依赖于 cs_id ,即只依赖于主键的一部分。
这种情况导致的问题是什么呢?
增:造成冗余。cs_name 重复出现,如果有许多武器的买主都是台湾,那么 cs_name 就会在这张表中出现很多次,造成浪费。
删:无
改:假如”菲律宾”后来改名了,那么数据库管理者不得不把表中所有 相关的 cs_name 全都改一遍。
查:无

第三范式
满足第二范式并且每个元组都不传递依赖于主键列。

CREATE TABLE province  
(  
    pr_id UNSIGNED INT NOT NULL AUTO_INCREMENT, -- 主键  
    pr_name VARCHAR(20) NOT NULL, -- 省份名, 完全依赖于主键, pr_id 定了, pr_name 就定了  
    PRIMARY KEY(pr_id)  
);  
CREATE TABLE city  
(  
    ct_id UNSIGNED INT NOT NULL AUTO_INCREMENT, -- 主键   
    ct_name VARCHAR(20) NOT NULL, -- 完全依赖于主键,ct_id 定了,ct_name 就定了  
    pr_id UNSIGNED INT NOT NULL , -- 完全依赖于主键,ct_id 定了,就可以确定 pr_id  
    pr_name VARCHAR(20) NOT NULL, -- 完全依赖于主键,ct_id 定了,就可以确定 pr_name  
    PRIMARY KEY(ct_id),  
    FOREIGN KEY(pr_id) REFERENCES province(pr_id) ON DELETE CASCADE  
);  

上述的这两张表都满足第二范式,不过,注意到 city 表中的 pr_name 元组虽然完全依赖于 ct_id , 但是它是通过 pr_id 传递依赖于 ct_id 的。

传递依赖的坏处:
增:明显 pr_name 出现冗余。
删:无
改:改动 province 表的 pr_name 元组,也要同时修改 city 表中的 pr_name 。一不小心就出问题。
查:无

反三范式

没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,提高读性能,就必须降低范式标准,适当保留冗余数据。具体做法是: 在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,减少了查询时的关联,提高查询效率,因为在数据库的操作中查询的比例要远远大于DML的比例。但是反范式化一定要适度,并且在原本已满足三范式的基础上再做调整的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值