- 浏览: 882910 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (509)
- android (55)
- CSS (23)
- eclipse (25)
- Data Structes and Algorithms (53)
- J2SE (87)
- Java_面试学习_j2se (26)
- java_面试学习_非技术 (13)
- java_gui (2)
- java_设计模式 (27)
- JDBC (10)
- java_web (15)
- hibernate (5)
- Oracle (37)
- Struts2 (7)
- Word-----dos (24)
- Jbpm (3)
- java小技巧 (8)
- math (1)
- flex (12)
- WebService (4)
- 生活 (9)
- 小框架或小语言 (27)
- spring (1)
- 面试~~~软实力 (7)
- jstat的用法 (1)
- jmap (1)
- 数据链路层和传输层的流量控制区别 (1)
- shell (0)
- 财商 (1)
- javascript (0)
- js研究 (1)
- 代码收集 (0)
最新评论
-
海尔群:
http://jingyan.baidu.com/articl ...
android加密 -
完美天龙:
------------------------- ...
asm----字节码操纵 -
houniao1990:
大神,请问 string 类型 定义为 oracle的 cha ...
hibernate注解 -
JamesQian:
Line:103
f.doFilter(msg);
是否需 ...
责任链模式_过滤器模式 -
sacoole:
好评
interview--- 如何从N个数中选出最大(小)的n个数?
第一范式:
列不可再分----实体属性不可再分
例如:学号---是不可再分的。 联系方式: 是可再分的,所以要换成 电话,邮箱等
第二范式:
每个非主属性依赖于任意候选键, 也就是说没与候选键有直接关系的就不要放入一个表中来。
比如:
姓名 选修课程 教材
张三 c++ c++完全手册
上面的这个例子中 教材和姓名是没有直接联系的,所以教材就不应该出现在这张表里面
更好的设计原则是: 分成两张表
姓名 选修课程 | 选修课程 教材
第三范式:
不能存在传递依赖;也就是说只能是直接依赖
比如说:
学号 姓名 班级 系别
如果我们知道一个学生的班级,那么我们可以推出他所在的系别,所以系别是可以通过班级来得出的,系别依赖于班级 而不依赖于学号
所以可以改成两张表:
学号 姓名 班级 ====== 班级 系别
//其实上面的是教科书上的东西。。。垃圾。。。。
看下面的通俗解释:
数据库范式:
从实际开发来看,如果真的全班照范式去做,则这个程序没法写了,
包括查询语句也会变得非常复杂
在Oracle中的scott用户的全部表,实际上就已经很好的体现了一种设计思路,
雇员--部门的关系
第一范式: 每个字段功能单一,一个字段不要做太多事情:(提高内聚性)
错误例子: info字段:“1986年11月出生,现在住在:北京市西城区”
正确例子: birthday 1986年11月,province:北京,eare:西城
但是也不能过了 比如 name最好不要分为first_name和last_name ,需要保证有意义就可以
如果全部按照第一范式的要求,也有问题
比如我们按照第一范式设计这样的表:
create table selectcourse(
stuno varchar2(50),
stuname varchar2(50),
stuage number,
cname varchar2(50),
grade number,
credit number
)
然后插入数据
insert into selectcourse values ('s001','张三',20,'java',89.0,3);
insert into selectcourse values ('s002','李四',20,'java',79.0,3);
insert into selectcourse values ('s003','王五',20,'java',80.0,3);
从以上的数据库创建脚本上可以发现,还存在以下问题,
1。所有的课程信息冗余,
2。如果一门课程没有一个学生选择,则此课程就从学校彻底消失了
3。课程本身应该有一个课程编号,但是如果按照以上设计,则课程编号肯定重复。
第二范式就是为了解决第二个问题的。。。
“ Java”这个非关键字段对“张三”"s003"这个候选关键字段有依赖
既然这个表中的课程依赖学生选课的结果,那么我们就应该吧课程表单独拿出来,
然后再建立一张关系表把学生和课程联系在一起
第三范式使用最多
现在要求设计一张学生表,包含学号,姓名,年龄,所在院校,学院地址,学院电话,此时肯定不能
使用第一范式,但是现在使用第二范式呢?
create table student(
stuno varchar2(50) primary key not null,
stuname varchar2(50),
stuage number
)
create table collage(
cid number(4) primary key not null,
cname varchar2(50) not null,
caddress varchar2(200) not null,
ctel varchar2(200) not null
);
create table studentcollage(
stuno varchar2(50),
cid number(4),
constraint student_studentcollage_stuno_fk foreign key(stuno) reference key(student.stuno) on delete cascade,
constraint collage_studentcollage_cid_fk foreign key(cid) reference key(collage.cid) on delete cascade
)
照这样的设计,一个学生可以同时在多个学院同时上课。 因为第二范式会使得两张表的关系是多对多的
最好的做法是:一个学院包含多个学生,一个学生属于一个学院
所以,去掉关系表,以父子关系在collage表上挂载学生表
create table collage(
cid number(4) primary key not null,
cname varchar2(50) not null,
caddress varchar2(200) not null,
ctel varchar2(200) not null
);
create table student(
stuno varchar2(50) primary key not null,
stuname varchar2(50),
stuage number,
cid number(4),
constraint student_cid_fk foregin key(cid) reference key(collage.cid) on delete cascade
)
如果真的按照此种设计方式设计数据库,则有够累,数据库唯一原则,
数据库的关联查询越少越好
============
数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。
设计范式是不是很难懂呢?非也,大学教材上给我们一堆数学公式我们当然看不懂,也记不住。所以我们很多人就根本不按照范式来设计数据库。
实质上,设计范式用很形象、很简洁的话语就能说清楚,道明白。本文将对范式进行通俗地说明,并以笔者曾经设计的一个简单论坛的数据库为例来讲解怎样将这些范式应用于实际工程。
范式说明
第一范式(1NF):数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。
例如,如下的数据库表是符合第一范式的:
字段1 字段2 字段3 字段4
而这样的数据库表是不符合第一范式的:
字段1 字段2 字段3 字段4
字段3.1 字段3.2
很显然,在当前的任何关系数据库管理系统(DBMS)中,傻瓜也不可能做出不符合第一范式的数据库,因为这些DBMS不允许你把数据库表的一列再分成二列或多列。因此,你想在现有的DBMS中设计出不符合第一范式的数据库都是不可能的。
第二范式(2NF):数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖(部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况),也即所有非关键字段都完全依赖于任意一组候选关键字。
假定选课关系表为SelectCourse(学号, 姓名, 年龄, 课程名称, 成绩, 学分),关键字为组合关键字(学号, 课程名称),因为存在如下决定关系:
(学号, 课程名称) → (姓名, 年龄, 成绩, 学分)
这个数据库表不满足第二范式,因为存在如下决定关系:
(课程名称) → (学分)
(学号) → (姓名, 年龄)
即存在组合关键字中的字段决定非关键字的情况。
由于不符合2NF,这个选课关系表会存在如下问题:
(1) 数据冗余:
同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。
(2) 更新异常:
若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。
(3) 插入异常:
假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。
(4) 删除异常:
假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。
把选课关系表SelectCourse改为如下三个表:
学生:Student(学号, 姓名, 年龄);
课程:Course(课程名称, 学分);
选课关系:SelectCourse(学号, 课程名称, 成绩)。
这样的数据库表是符合第二范式的, 消除了数据冗余、更新异常、插入异常和删除异常。
另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字。
第三范式(3NF):在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖,指的是如果存在"A → B → C"的决定关系,则C传递函数依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系:
关键字段 → 非关键字段x → 非关键字段y
假定学生关系表为Student(学号, 姓名, 年龄, 所在学院, 学院地点, 学院电话),关键字为单一关键字"学号",因为存在如下决定关系:
(学号) → (姓名, 年龄, 所在学院, 学院地点, 学院电话)
这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系:
(学号) → (所在学院) → (学院地点, 学院电话)
即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。
它也会存在数据冗余、更新异常、插入异常和删除异常的情况,读者可自行分析得知。
把学生关系表分为如下两个表:
学生:(学号, 姓名, 年龄, 所在学院);
学院:(学院, 地点, 电话)。
这样的数据库表是符合第三范式的,消除了数据冗余、更新异常、插入异常和删除异常。
鲍依斯-科得范式(BCNF):在第三范式的基础上,数据库表中如果不存在任何字段对任一候选关键字段的传递函数依赖则符合第三范式。
假设仓库管理关系表为StorehouseManage(仓库ID, 存储物品ID, 管理员ID, 数量),且有一个管理员只在一个仓库工作;一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:
(仓库ID, 存储物品ID) →(管理员ID, 数量)
(管理员ID, 存储物品ID) → (仓库ID, 数量)
所以,(仓库ID, 存储物品ID)和(管理员ID, 存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
(仓库ID) → (管理员ID)
(管理员ID) → (仓库ID)
即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。它会出现如下异常情况:
(1) 删除异常:
当仓库被清空后,所有"存储物品ID"和"数量"信息被删除的同时,"仓库ID"和"管理员ID"信息也被删除了。
(2) 插入异常:
当仓库没有存储任何物品时,无法给仓库分配管理员。
(3) 更新异常:
如果仓库换了管理员,则表中所有行的管理员ID都要修改。
把仓库管理关系表分解为二个关系表:
仓库管理:StorehouseManage(仓库ID, 管理员ID);
仓库:Storehouse(仓库ID, 存储物品ID, 数量)。
这样的数据库表是符合BCNF范式的,消除了删除异常、插入异常和更新异常。
范式应用
我们来逐步搞定一个论坛的数据库,有如下信息:
(1) 用户:用户名,email,主页,电话,联系地址
(2) 帖子:发帖标题,发帖内容,回复标题,回复内容
第一次我们将数据库设计为仅仅存在表:
用户名 email 主页 电话 联系地址 发帖标题 发帖内容 回复标题 回复内容
这个数据库表符合第一范式,但是没有任何一组候选关键字能决定数据库表的整行,唯一的关键字段用户名也不能完全决定整个元组。我们需要增加"发帖ID"、"回复ID"字段,即将表修改为:
用户名 email 主页 电话 联系地址 发帖ID 发帖标题 发帖内容 回复ID 回复标题 回复内容
这样数据表中的关键字(用户名,发帖ID,回复ID)能决定整行:
(用户名,发帖ID,回复ID) → (email,主页,电话,联系地址,发帖标题,发帖内容,回复标题,回复内容)
但是,这样的设计不符合第二范式,因为存在如下决定关系:
(用户名) → (email,主页,电话,联系地址)
(发帖ID) → (发帖标题,发帖内容)
(回复ID) → (回复标题,回复内容)
即非关键字段部分函数依赖于候选关键字段,很明显,这个设计会导致大量的数据冗余和操作异常。
我们将数据库表分解为(带下划线的为关键字):
(1) 用户信息:用户名,email,主页,电话,联系地址
(2) 帖子信息:发帖ID,标题,内容
(3) 回复信息:回复ID,标题,内容
(4) 发贴:用户名,发帖ID
(5) 回复:发帖ID,回复ID
这样的设计是满足第1、2、3范式和BCNF范式要求的,但是这样的设计是不是最好的呢?
不一定。
观察可知,第4项"发帖"中的"用户名"和"发帖ID"之间是1:N的关系,因此我们可以把"发帖"合并到第2项的"帖子信息"中;第5项"回复"中的"发帖ID"和"回复ID"之间也是1:N的关系,因此我们可以把"回复"合并到第3项的"回复信息"中。这样可以一定量地减少数据冗余,新的设计为:
(1) 用户信息:用户名,email,主页,电话,联系地址
(2) 帖子信息:用户名,发帖ID,标题,内容
(3) 回复信息:发帖ID,回复ID,标题,内容
数据库表1显然满足所有范式的要求;
数据库表2中存在非关键字段"标题"、"内容"对关键字段"发帖ID"的部分函数依赖,即不满足第二范式的要求,但是这一设计并不会导致数据冗余和操作异常;
数据库表3中也存在非关键字段"标题"、"内容"对关键字段"回复ID"的部分函数依赖,也不满足第二范式的要求,但是与数据库表2相似,这一设计也不会导致数据冗余和操作异常。
由此可以看出,并不一定要强行满足范式的要求,对于1:N关系,当1的一边合并到N的那边后,N的那边就不再满足第二范式了,但是这种设计反而比较好!
对于M:N的关系,不能将M一边或N一边合并到另一边去,这样会导致不符合范式要求,同时导致操作异常和数据冗余。
对于1:1的关系,我们可以将左边的1或者右边的1合并到另一边去,设计导致不符合范式要求,但是并不会导致操作异常和数据冗余。
结论
满足范式要求的数据库设计是结构清晰的,同时可避免数据冗余和操作异常。这并意味着不符合范式要求的设计一定是错误的,在数据库表中存在1:1或1:N关系这种较特殊的情况下,合并导致的不符合范式要求反而是合理的。
列不可再分----实体属性不可再分
例如:学号---是不可再分的。 联系方式: 是可再分的,所以要换成 电话,邮箱等
第二范式:
每个非主属性依赖于任意候选键, 也就是说没与候选键有直接关系的就不要放入一个表中来。
比如:
姓名 选修课程 教材
张三 c++ c++完全手册
上面的这个例子中 教材和姓名是没有直接联系的,所以教材就不应该出现在这张表里面
更好的设计原则是: 分成两张表
姓名 选修课程 | 选修课程 教材
第三范式:
不能存在传递依赖;也就是说只能是直接依赖
比如说:
学号 姓名 班级 系别
如果我们知道一个学生的班级,那么我们可以推出他所在的系别,所以系别是可以通过班级来得出的,系别依赖于班级 而不依赖于学号
所以可以改成两张表:
学号 姓名 班级 ====== 班级 系别
//其实上面的是教科书上的东西。。。垃圾。。。。
看下面的通俗解释:
数据库范式:
从实际开发来看,如果真的全班照范式去做,则这个程序没法写了,
包括查询语句也会变得非常复杂
在Oracle中的scott用户的全部表,实际上就已经很好的体现了一种设计思路,
雇员--部门的关系
第一范式: 每个字段功能单一,一个字段不要做太多事情:(提高内聚性)
错误例子: info字段:“1986年11月出生,现在住在:北京市西城区”
正确例子: birthday 1986年11月,province:北京,eare:西城
但是也不能过了 比如 name最好不要分为first_name和last_name ,需要保证有意义就可以
如果全部按照第一范式的要求,也有问题
比如我们按照第一范式设计这样的表:
create table selectcourse(
stuno varchar2(50),
stuname varchar2(50),
stuage number,
cname varchar2(50),
grade number,
credit number
)
然后插入数据
insert into selectcourse values ('s001','张三',20,'java',89.0,3);
insert into selectcourse values ('s002','李四',20,'java',79.0,3);
insert into selectcourse values ('s003','王五',20,'java',80.0,3);
从以上的数据库创建脚本上可以发现,还存在以下问题,
1。所有的课程信息冗余,
2。如果一门课程没有一个学生选择,则此课程就从学校彻底消失了
3。课程本身应该有一个课程编号,但是如果按照以上设计,则课程编号肯定重复。
第二范式就是为了解决第二个问题的。。。
“ Java”这个非关键字段对“张三”"s003"这个候选关键字段有依赖
既然这个表中的课程依赖学生选课的结果,那么我们就应该吧课程表单独拿出来,
然后再建立一张关系表把学生和课程联系在一起
第三范式使用最多
现在要求设计一张学生表,包含学号,姓名,年龄,所在院校,学院地址,学院电话,此时肯定不能
使用第一范式,但是现在使用第二范式呢?
create table student(
stuno varchar2(50) primary key not null,
stuname varchar2(50),
stuage number
)
create table collage(
cid number(4) primary key not null,
cname varchar2(50) not null,
caddress varchar2(200) not null,
ctel varchar2(200) not null
);
create table studentcollage(
stuno varchar2(50),
cid number(4),
constraint student_studentcollage_stuno_fk foreign key(stuno) reference key(student.stuno) on delete cascade,
constraint collage_studentcollage_cid_fk foreign key(cid) reference key(collage.cid) on delete cascade
)
照这样的设计,一个学生可以同时在多个学院同时上课。 因为第二范式会使得两张表的关系是多对多的
最好的做法是:一个学院包含多个学生,一个学生属于一个学院
所以,去掉关系表,以父子关系在collage表上挂载学生表
create table collage(
cid number(4) primary key not null,
cname varchar2(50) not null,
caddress varchar2(200) not null,
ctel varchar2(200) not null
);
create table student(
stuno varchar2(50) primary key not null,
stuname varchar2(50),
stuage number,
cid number(4),
constraint student_cid_fk foregin key(cid) reference key(collage.cid) on delete cascade
)
如果真的按照此种设计方式设计数据库,则有够累,数据库唯一原则,
数据库的关联查询越少越好
============
数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。
设计范式是不是很难懂呢?非也,大学教材上给我们一堆数学公式我们当然看不懂,也记不住。所以我们很多人就根本不按照范式来设计数据库。
实质上,设计范式用很形象、很简洁的话语就能说清楚,道明白。本文将对范式进行通俗地说明,并以笔者曾经设计的一个简单论坛的数据库为例来讲解怎样将这些范式应用于实际工程。
范式说明
第一范式(1NF):数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。
例如,如下的数据库表是符合第一范式的:
字段1 字段2 字段3 字段4
而这样的数据库表是不符合第一范式的:
字段1 字段2 字段3 字段4
字段3.1 字段3.2
很显然,在当前的任何关系数据库管理系统(DBMS)中,傻瓜也不可能做出不符合第一范式的数据库,因为这些DBMS不允许你把数据库表的一列再分成二列或多列。因此,你想在现有的DBMS中设计出不符合第一范式的数据库都是不可能的。
第二范式(2NF):数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖(部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况),也即所有非关键字段都完全依赖于任意一组候选关键字。
假定选课关系表为SelectCourse(学号, 姓名, 年龄, 课程名称, 成绩, 学分),关键字为组合关键字(学号, 课程名称),因为存在如下决定关系:
(学号, 课程名称) → (姓名, 年龄, 成绩, 学分)
这个数据库表不满足第二范式,因为存在如下决定关系:
(课程名称) → (学分)
(学号) → (姓名, 年龄)
即存在组合关键字中的字段决定非关键字的情况。
由于不符合2NF,这个选课关系表会存在如下问题:
(1) 数据冗余:
同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。
(2) 更新异常:
若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。
(3) 插入异常:
假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。
(4) 删除异常:
假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。
把选课关系表SelectCourse改为如下三个表:
学生:Student(学号, 姓名, 年龄);
课程:Course(课程名称, 学分);
选课关系:SelectCourse(学号, 课程名称, 成绩)。
这样的数据库表是符合第二范式的, 消除了数据冗余、更新异常、插入异常和删除异常。
另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字。
第三范式(3NF):在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖,指的是如果存在"A → B → C"的决定关系,则C传递函数依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系:
关键字段 → 非关键字段x → 非关键字段y
假定学生关系表为Student(学号, 姓名, 年龄, 所在学院, 学院地点, 学院电话),关键字为单一关键字"学号",因为存在如下决定关系:
(学号) → (姓名, 年龄, 所在学院, 学院地点, 学院电话)
这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系:
(学号) → (所在学院) → (学院地点, 学院电话)
即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。
它也会存在数据冗余、更新异常、插入异常和删除异常的情况,读者可自行分析得知。
把学生关系表分为如下两个表:
学生:(学号, 姓名, 年龄, 所在学院);
学院:(学院, 地点, 电话)。
这样的数据库表是符合第三范式的,消除了数据冗余、更新异常、插入异常和删除异常。
鲍依斯-科得范式(BCNF):在第三范式的基础上,数据库表中如果不存在任何字段对任一候选关键字段的传递函数依赖则符合第三范式。
假设仓库管理关系表为StorehouseManage(仓库ID, 存储物品ID, 管理员ID, 数量),且有一个管理员只在一个仓库工作;一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:
(仓库ID, 存储物品ID) →(管理员ID, 数量)
(管理员ID, 存储物品ID) → (仓库ID, 数量)
所以,(仓库ID, 存储物品ID)和(管理员ID, 存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
(仓库ID) → (管理员ID)
(管理员ID) → (仓库ID)
即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。它会出现如下异常情况:
(1) 删除异常:
当仓库被清空后,所有"存储物品ID"和"数量"信息被删除的同时,"仓库ID"和"管理员ID"信息也被删除了。
(2) 插入异常:
当仓库没有存储任何物品时,无法给仓库分配管理员。
(3) 更新异常:
如果仓库换了管理员,则表中所有行的管理员ID都要修改。
把仓库管理关系表分解为二个关系表:
仓库管理:StorehouseManage(仓库ID, 管理员ID);
仓库:Storehouse(仓库ID, 存储物品ID, 数量)。
这样的数据库表是符合BCNF范式的,消除了删除异常、插入异常和更新异常。
范式应用
我们来逐步搞定一个论坛的数据库,有如下信息:
(1) 用户:用户名,email,主页,电话,联系地址
(2) 帖子:发帖标题,发帖内容,回复标题,回复内容
第一次我们将数据库设计为仅仅存在表:
用户名 email 主页 电话 联系地址 发帖标题 发帖内容 回复标题 回复内容
这个数据库表符合第一范式,但是没有任何一组候选关键字能决定数据库表的整行,唯一的关键字段用户名也不能完全决定整个元组。我们需要增加"发帖ID"、"回复ID"字段,即将表修改为:
用户名 email 主页 电话 联系地址 发帖ID 发帖标题 发帖内容 回复ID 回复标题 回复内容
这样数据表中的关键字(用户名,发帖ID,回复ID)能决定整行:
(用户名,发帖ID,回复ID) → (email,主页,电话,联系地址,发帖标题,发帖内容,回复标题,回复内容)
但是,这样的设计不符合第二范式,因为存在如下决定关系:
(用户名) → (email,主页,电话,联系地址)
(发帖ID) → (发帖标题,发帖内容)
(回复ID) → (回复标题,回复内容)
即非关键字段部分函数依赖于候选关键字段,很明显,这个设计会导致大量的数据冗余和操作异常。
我们将数据库表分解为(带下划线的为关键字):
(1) 用户信息:用户名,email,主页,电话,联系地址
(2) 帖子信息:发帖ID,标题,内容
(3) 回复信息:回复ID,标题,内容
(4) 发贴:用户名,发帖ID
(5) 回复:发帖ID,回复ID
这样的设计是满足第1、2、3范式和BCNF范式要求的,但是这样的设计是不是最好的呢?
不一定。
观察可知,第4项"发帖"中的"用户名"和"发帖ID"之间是1:N的关系,因此我们可以把"发帖"合并到第2项的"帖子信息"中;第5项"回复"中的"发帖ID"和"回复ID"之间也是1:N的关系,因此我们可以把"回复"合并到第3项的"回复信息"中。这样可以一定量地减少数据冗余,新的设计为:
(1) 用户信息:用户名,email,主页,电话,联系地址
(2) 帖子信息:用户名,发帖ID,标题,内容
(3) 回复信息:发帖ID,回复ID,标题,内容
数据库表1显然满足所有范式的要求;
数据库表2中存在非关键字段"标题"、"内容"对关键字段"发帖ID"的部分函数依赖,即不满足第二范式的要求,但是这一设计并不会导致数据冗余和操作异常;
数据库表3中也存在非关键字段"标题"、"内容"对关键字段"回复ID"的部分函数依赖,也不满足第二范式的要求,但是与数据库表2相似,这一设计也不会导致数据冗余和操作异常。
由此可以看出,并不一定要强行满足范式的要求,对于1:N关系,当1的一边合并到N的那边后,N的那边就不再满足第二范式了,但是这种设计反而比较好!
对于M:N的关系,不能将M一边或N一边合并到另一边去,这样会导致不符合范式要求,同时导致操作异常和数据冗余。
对于1:1的关系,我们可以将左边的1或者右边的1合并到另一边去,设计导致不符合范式要求,但是并不会导致操作异常和数据冗余。
结论
满足范式要求的数据库设计是结构清晰的,同时可避免数据冗余和操作异常。这并意味着不符合范式要求的设计一定是错误的,在数据库表中存在1:1或1:N关系这种较特殊的情况下,合并导致的不符合范式要求反而是合理的。
发表评论
-
函数---merge
2011-06-25 10:37 3312/*Merge into 详细介绍 MERGE语句是Or ... -
函数---keep
2011-06-23 08:07 1123KEEP 看到很多人对于keep不理解,这里解释一下 ... -
函数---GROUPING
2011-06-23 07:35 977GROUPING GROUPING函数可以接受一列,返回 ... -
函数---trunc,LEAST,COALESCE ,TRANSLATE,convert,REPLACE
2011-06-16 09:44 1146select trunc(sysdate,'DD') AA ... -
函数---to_char,RANK()和dense_rank(),rollup,cube
2011-06-16 07:53 1340TO_CHAR(<x> [,<fmt & ... -
oracle-----list,array
2011-06-12 18:47 1139定义 type idList_type is table ... -
oracle----触发器
2011-06-12 15:14 995这个触发器的作用是在插入role_info表的时候把rol ... -
oracle---包,游标
2011-06-11 20:40 1483游标就是一个指向内 ... -
函数---instr
2011-05-29 10:29 21421.instr 在Oracle/PLSQL中,instr函 ... -
oracle经典博文
2011-04-18 13:05 986http://www.itpub.net/viewthread ... -
oracle-----转换函数
2011-04-17 14:45 1220Oracle 中的 TO_DATE 和 TO_CHAR 函 ... -
sql-------not in 与not exists效率
2011-01-19 09:28 2156总结: not exists总比not in好, in在内 ... -
oracle----globle temp table
2010-12-01 17:56 1214在sybase中的存储过程可以写临时表,但是oracle不 ... -
oracle----函数收集
2010-11-30 16:38 1656日期函数 1.ADD_MONTHS( ... -
sybase----函数收集
2010-11-30 16:36 1175长度和语法分析 datalength(char_expr ... -
sybase----oracle ---函数转换
2010-11-30 16:31 1381比如: 1.select user_id,convert ... -
oracle----块编程
2010-11-30 15:17 17331.块的构成:---这里不 ... -
sybase---oracle2sybase procedure
2010-11-03 19:35 1093Oracle的存储过程 create or repl ... -
sybase---bcp
2010-11-03 19:31 2008bcp 数据库名..表名 in ... -
oracle---用户管理
2010-10-06 19:37 1521sys是超级管理员,他比s ...
相关推荐
数据库设计的三大范式——第一范式(1NF)、第二范式(2NF)和第三范式(3NF)——是确保数据结构合理化、减少数据冗余和避免操作异常的关键概念...通过实例分析和实际操作,可以更好地理解和掌握这些数据库设计原则。
【数据库设计中的范式规则详解】 数据库设计是构建高效、稳定、可靠的信息系统的基础,而范式规则则是数据库设计...因此,设计师需要根据业务需求、系统规模和预期负载灵活应用范式理论,以达到最佳的数据库设计方案。
数据库设计三范式是数据库规范化理论中的核心概念,主要用于优化数据存储,避免数据冗余和更新异常。这里我们将深入探讨第一范式(1NF)和第二范式(2NF)。 **第一范式(1NF)** 第一范式强调的是列的原子性,即每...
数据库范式化是数据库设计中保证数据关系清晰、降低数据冗余和提高数据一致性的过程。...通过阅读和实践本教程,读者可以对数据库结构有一个清晰的理解,并学会如何应用范式化原则来优化数据库设计。
数据库设计是数据挖掘过程中的重要基础,而三范式(3NF)是关系数据库设计中的核心理论之一。本文将深入探讨三范式及其在数据库设计中的应用,旨在为数据挖掘提供坚实的理论支持。 首先,我们需要了解数据库设计的...
这通常基于规范化理论,它是一套指导原则,帮助设计师创建科学合理的关系模式。 关系数据库的完整性规则是规范化理论的重要组成部分,包括实体完整性、参照完整性和用户定义完整性。实体完整性规定,关系中的主键...
### 数据库设计原则——规范化详解 #### 一、引言 在关系数据库设计过程中,规范化是一种重要的设计方法,它能够帮助我们减少数据冗余、提高数据完整性并优化数据存储效率。随着项目的扩大,数据库设计变得越来越...
关系数据库理论是数据库管理系统设计的核心概念,它基于数学中的关系模型。关系数据库理论主要关注如何组织和操作数据,以确保数据的一致性、减少冗余并优化查询性能。本篇内容将围绕关系数据库的规范化理论展开,...
4. **数据库范式理论**:为了减少数据冗余和提高数据一致性,数据库通常需要遵循一定的范式,如第一范式(1NF)、第二范式(2NF)到第三范式(3NF),甚至更高阶的BCNF(Boyce-Codd范式)。 5. **数据库安全性**:...
第三范式是数据库设计的一个基本原则,它要求表中的非主键属性只依赖于主键属性,从而消除冗余数据和数据不一致性。遵循3NF设计的优点包括: - **节省存储空间**:由于消除了冗余数据,减少了磁盘占用。 - **数据...
数据库范式是数据库设计中的一个重要概念,用于优化数据存储,减少数据冗余并避免数据不一致性。这个概念源自于关系数据库...通过学习和实践,你可以更好地掌握数据库设计的核心原则,为你的职业生涯打下坚实的基础。
在实际工程中,规范化不仅仅包括范式的应用,还涉及到其他设计原则,如合理设置索引、考虑数据访问模式、优化查询性能等。设计者应当根据项目的具体需求,灵活运用规范化原则,以达到最优的数据库设计方案。 总之,...
数据库设计范式是关系数据库设计的核心概念,它们是用来确保数据的一致性、减少冗余、避免数据异常的关键原则。在数据库领域,特别是Oracle等大型关系型数据库系统中,理解和掌握这些范式至关重要。 首先,第一范式...
本文主要探讨了几个关键的数据库设计原则,包括各种范式标准、E-R图、三少原则以及提高数据库运行效率的方法。 首先,原始单据与实体之间的关系在数据库设计中起到基础作用。通常,原始单据可以一对一、一对多或多...
数据库设计是信息系统构建的核心环节,其中的三大范式——第一范式、第二范式和第三范式,是确保数据规范化和避免数据冗余的关键原则。这些范式是根据关系数据库理论建立的,目的是提高数据库的逻辑独立性和减少数据...
数据库设计与开发是软件工程研究生课程中的核心部分,它涵盖了数据管理、数据库系统架构、查询语言、数据库设计原则以及数据库应用程序开发等多个方面。这个压缩包文件"软件工程研究生的课程---数据库设计开发.rar...
在数据库设计中,范式是一种规范化理论,旨在减少数据冗余和提高数据一致性。范式分为不同级别,如1NF(第一范式)、2NF(第二范式)和3NF(第三范式)。1NF要求数据具有原子性,确保每个字段只包含单一值;2NF强调...
数据库课程设计是IT领域中一个重要的实践环节,它通常涵盖了数据模型、数据库管理系统(DBMS)、SQL语言、数据库设计原则等多个方面。在这个“考试类精品--数据库课程设计-考试系统”项目中,我们可以深入探讨如何...
【第六章 - 关系数据理论 - 规范化】 关系数据理论是数据库设计的基础,其中规范化是优化数据库结构的关键...在实际应用中,数据库设计师需要仔细分析数据依赖,遵循规范化原则,以构建符合不同范式级别的关系模式。