数据库设计范式
数据库范式是一个很重要的概念,在实际设计数据库架构时仅供参考,遵循数据库的设计范式可以让数据表更好的保存数据,但是再合理的设计也会由于数据量过大存在性能问题,在实际开发设计中应该遵循设计的时候尽量避免日后的多表关联查询。
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)
三大范式只是设计数据库的基本理念,实际开发按照,需求>性能>表结构的设计理念,不能一味的去追求范式建立数据库。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?