目录

MySQL数据库之三大设计范式

何为范式

设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。

第一范式

数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。即实体中的某个属性有多个值时,必须拆分为不同的属性。在符合第一范式(1NF)表中的每个域值只能是实体的一个属性或一个属性的一部分。简而言之,第一范式就是无重复的域。 即拆分字段

create table student2(
	id int primary key,
	name varchar(20),
	address varchar(30)
);

insert into student2 values(1,'张三','中国四川省成都市武侯区武侯大道100号');
insert into student2 values(2,'李四','中国四川省成都市武侯区京城大道200号');
insert into student2 values(3,'王五','中国四川省成都市高新区天府大道90号');

mysql> select * from student2;   
+----+--------+-----------------------------------------------------+
| id | name   | address                                             |
+----+--------+-----------------------------------------------------+
|  1 | 张三   | 中国四川省成都市武侯区武侯大道100号                 |
|  2 | 李四   | 中国四川省成都市武侯区京城大道200号                 |
|  3 | 王五   | 中国四川省成都市高新区天府大道90号                  |
+----+--------+-----------------------------------------------------+
3 rows in set (0.00 sec)

因为字段值还可以继续拆分的,所以就不满足第一范式,因此需要做如下拆分

create table student3(
	id int primary key,
	name varchar(20),
	cuntry varchar(30),
	privence varchar(30),
	city varchar(30),
	details varchar(30)
);

insert into student3 values(1,'张三','中国','四川省','成都市','武侯区武侯大道100号');
insert into student3 values(2,'李四','中国','四川省','成都市','武侯区京城大道200号');
insert into student3 values(3,'王五','中国','四川省','成都市','高新区天府大道90号');

mysql> select * from student3;
+----+--------+--------+-----------+-----------+-----------------------------+
| id | name   | cuntry | privence  | city      | details                     |
+----+--------+--------+-----------+-----------+-----------------------------+
|  1 | 张三   | 中国   | 四川省    | 成都市    | 武侯区武侯大道100号         |
|  2 | 李四   | 中国   | 四川省    | 成都市    | 武侯区京城大道200号         |
|  3 | 王五   | 中国   | 四川省    | 成都市    | 高新区天府大道90号          |
+----+--------+--------+-----------+-----------+-----------------------------+
3 rows in set (0.00 sec)

范式,设计的越详细,对于某些实际操作可能更好,但是不一定都是好处。

第二范式

要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是在第一范式的基础上属性完全依赖于主键。 联合约束可能会出现第二范式不满足的情况

订单表
create table myorder(
	product_id int,
	customer_id int,
	product_name varchar(20),
	customer_name varchar(20),
	primary key(product_id,customer_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)
);

分成三个表之后,就满足了第二范式的设计!!

第三范式

必须先满足第二范式,除主键列的其他列之间不能有传递依赖关系。

create table myorder(
	order_id int primary key,
	product_id int,
	customer_id int,
  customer_phone varchar(11)
);

可看出customer_phone是与customer_id有关系的,即通过customer_id可以对应找到customer_id的,故有冗余,应将其分开

create table customer(
	id int primary key,
	name varchar(20),
	phone varchar(15)
);