当数据模型从概念层转到逻辑层时,需要进行规范化设计。要想设计一个结构合理的关系型数据库,至少需要满足1NF,2NF,3NF,即第一范式,第二范式,第三范式。
1,1NF(原子性)
1NF是最基本的,数据库表的每一列都是不可分割的原子数据项。
不可分割是相对而言的,依据实际需求来界定。
严格的说,某些TSQL的系统数据类型违反1NF,例如DateTime类型,包含了year,month,day,hour,minute,second,millisecond,但是我们更希望这些属性组合在一起,标识事情发生的具体时间点。
1NF提供了一种规范,优秀的设计模型,例如 姓名(full name)包含两部分,姓氏和名字,如果应用程序不会分别获取姓氏或名字,可以将full name视为原子数据项,但是,如果程序需要获取姓氏或名字,那么将full name拆分,划分为两列(surname 和 name)是更好的设计模型。
2,2NF(属性完全依赖于主键)
表中的所有列,都必须完全依赖于主键,由主键唯一标识所有属性列,对于不完全依赖于主键的列,会出现数据冗余,需要拆分成表。
例如以下是个成绩表,各个字段的含义是 Cid(course id),Cname(course name),stuid(student id),stuname(student name),主键是cid和stuid,但是cname,stuname,professionid和professionname并不完全依赖于主键,cname完全依赖于CID,stuname,professionid和professionname完全依赖于stuid。
按照2NF的要求,将依赖于主键属性的所有属性集中到一个表中,上图数据能拆分成三个表,dbo.student,dbo.course,dbo.score,消除数据的冗余。
表是属性的集合,一个表是一个实体,例如student表,有学号,name,profession属性,学号是主键属性,能唯一标识一个student实体,能够根据学号唯一确定一位学生的name,profession属性。
create table dbo.student(stuid int not null primary key,stuname varchar(100) not null,professionid int ,professionname varchar(100))create table dbo.course(cid int not null primary key,cname varchar(100) not null)create table dbo.score(cid int not null foreign key references dbo.course(cid),stuid int not null foreign key references dbo.student(stuid),score int nullprimary key(cid,stuid))
3,3NF(属性不能传递依赖于主属性,即属性不依赖于其它非主键属性)
如果某一属性A依赖于非主键属性B,而非主键属性B依赖于主键pk,那么属性A就是间接依赖于主键pk,这被称作传递依赖于主属性。
例如,ProfessioName 是专业名称,每一个专业的名称是唯一的,跟学生没有关系,ProfessioName依赖于ProfessionID,而ProfessionID完全依赖于stuid,因为student表的属性是由stuid唯一标识的,所以ProfessioName传递依赖于stuid。
对传递依赖进行范化,需要将传递依赖的属性拆分成表,例如
create table dbo.profession( professionid int not null primary key, professionname varchar(100))create table dbo.student( stuid int not null primary key, stuname varchar(100) not null, professionid int foreign key references dbo.profession(professionid))