简述
- 1NF:字段不可拆分
- 2NF:有主键,非主键字段依赖主键
- 3NF:非主键字段不能互相依赖
1NF
属性不可分割,即每个属性都是不可分割的原子项(实体中的属性即表中的列)。只要字段值还可以继续拆分,就不满足第一范式。
例如:数据表中存在address地址该属性,若每条数据的值为“xx省xx市
”,则该属性即可分割属性,分为“xx省
”、“xx市
”两个属性。
范式设计得越详细,对某些实际操作可能会更好,但并非都有好处,需要对项目的实际情况进行设定,并非必须遵守该范式。
2NF
在满足第一范式的前提下,其他列都必须完全依赖于主键列。
如果出现不完全依赖,只可能发生在联合主键的情况下。
例如某订单表为:
-- 订单表
CREATE TABLE myorder (
product_id INT,
customer_id INT,
product_name VARCHAR(20),
customer_name VARCHAR(20),
PRIMARY KEY (product_id, customer_id)
);
若product_name
只依赖于 product_id
,customer_name
只依赖于 customer_id
。product_name
和 customer_id
是没有关系的,customer_name
和 product_id
也是没有关系的。
这就不满足第二范式:其他列都必须完全依赖于主键列!
需要做如下改进:
CREATE TABLE myorder (
order_id INT PRIMARY KEY,
product_id INT,
customer_id INT
);
CREATE TABLE product (
id INT PRIMARY KEY,
name VARCHAR(20)
);
CREATE TABLE customer (
id INT PRIMARY KEY,
name VARCHAR(20)
);
拆分之后,myorder
表中的 product_id
和 customer_id
完全依赖于 order_id
主键,而 product
和 customer
表中的其他字段又完全依赖于主键,即满足第二范式。
3NF
在满足第二范式的前提下,除了主键列之外,其他列之间不能有传递依赖关系。
CREATE TABLE myorder (
order_id INT PRIMARY KEY,
product_id INT,
customer_id INT,
customer_phone VARCHAR(20)
);
表中的 customer_phone
有也许依赖于 customer_id
,也就不满足第三范式:其他列之间不能有传递依赖关系。
改进:
CREATE TABLE myorder (
order_id INT PRIMARY KEY,
product_id INT,
customer_id INT
);
CREATE TABLE customer (
id INT PRIMARY KEY,
name VARCHAR(20),
phone VARCHAR(20)
);
修改后就不存在其他列之间的传递依赖关系,其他列都只依赖于主键列,满足了第三范式的设计!
面试相关
如何通俗理解三个范式?
- 第一范式是对原子性的约束,要求属性具有原子性,不可拆分。
- 第二范式是对记录的唯一性约束,要求具有唯一标识,即实体的唯一性
- 第三范式是对字段冗余性的约束,即任何字段不能由其他字段派生出来
范式设计的优缺点?
- 优点:减少数据冗余
- 缺点:查询时需要关联多个表,更难进行索引优化
参考:
https://www.bilibili.com/video/BV1Vt411z7wy