数据库设计范式
数据库范式是一个很重要的概念,在实际设计数据库架构时仅供参考,遵循数据库的设计范式可以让数据表更好的保存数据,但是再合理的设计也会由于数据量过大存在性能问题,在实际开发设计中应该遵循设计的时候尽量避免日后的多表关联查询。
1 第一范式,数据表中的每列数据不可再分,确保每一列的原子性;两列的属性相近或相似或一样,尽量合并属性一样的列,确保不产生冗余数据;如下表设计:
create table Test1
(
id number primary key,
name varchar2(50) not null,
contact varchar(200) not null
);
此设计不符合第一范式,因为contact可以再分为电话,地址,email等等,符合第一范式的设计应该为:
create table Test1
(
id number primary key,
name varchar2(50) not null,
cell phone varchar(20) not null,
address varchar(200) not null,
email varchar(50) not null
);
create table Test1
(
id1 number not null,
name1 varchar2(50) not null,
id2 number not null,
name2 varchar2(50) not null
)
此设计有相似的列,应该合并为一列;
2 第二范式,数据库表中的非关键字段存在对任一候选关键字的部分函数依赖;每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开来。
理解一:列之间不应该存在函数关系,如下设计
create table Test2
(
id number primary key,
name varchar2(20),
price number,
allprice number
);
allprice = price*amount,存在函数依赖关系
理解二:看如下设计,学生选课系统
create table student_course
(
stuid number primary key,
stuname varchar2(20) not null,
cname varchar2(20) not nul,
credit number not null,
score number
)
此设计符合第一范式,但是不符合第二范式,因为程序存在以下问题
insert into student_course(stuid, stuname, cname, credit, score) values(1, '张三', 'Java', 3, 80);
insert into student_course(stuid, stuname, cname, credit, score) values(2, '李四', 'Java', 3, 90);
insert into student_course(stuid, stuname, cname, credit, score) values(3, '王五', 'Java', 3, 70);
insert into student_course(stuid, stuname, cname, credit, score) values(1, '张三', 'Oracle', 2, 90);
insert into student_course(stuid, stuname, cname, credit, score) values(2, '李四', 'Oracle', 2, 60);
可以发现数据重复,学生与课程数据都存在重复;数据更新时非常影响性能,如果需要更新一门课程的学分,则需要更新所有选了这门课程的记录;符合第二范式的设计应为:
create table student
(
stuid number primary key,
stuname varchar2(20) not null,
)
create table course
(
cid number primary key,
cname varchar2(50) not null,
credit number not null
)
create table student_course
(
stuid number not null,
cid number not null,
score number not null
)
insert into student(stuid, stuname) values('1', '张三');
insert into student(stuid, stuname) values('2', '李四');
insert into student(stuid, stuname) values('3', '王五');
insert into course(cid, cname, credit) values(101, 'Java', 3);
insert into course(cid, cname, credit) values(102, 'Oracle', 2);
insert into course(cid, cname, credit) values(103, 'Linux', 4);
insert into student_course(stuid, cid, score) values (1, 101, 80);
insert into student_course(stuid, cid, score) values (1, 102, 90);
insert into student_course(stuid, cid, score) values (1, 103, 70);
insert into student_course(stuid, cid, score) values (2, 101, 60);
insert into student_course(stuid, cid, score) values (2, 102, 70);
insert into student_course(stuid, cid, score) values (2, 103, 50);
第二范式是多对多的表设计方式
3 第三范式,数据不能存在传递关系,即每个属性都跟主键有直接关系而不是间接关系。像:a-->b-->c 属性之间含有这样的关系,是不符合第三范式。一个学校有多个学生,第一范式无法实现,第二范式也不能实现,一个学生只属于一个学校,此时可以使用第三范式,
不符合第三范式的设计
student(stuid, stuname, cellphone, sid, sname, saddress)
这样一个表结构,就存在上述关系。 stuid--> sid--> (sname, saddress)
应拆分为 student(stuid, stuname, cellphone,sid) school(sid, sname,saddress)
三大范式只是设计数据库的基本理念,实际开发按照,需求>性能>表结构的设计理念,不能一味的去追求范式建立数据库。