现在的位置: 首页 > 综合 > 正文

数据库范式

2013年10月15日 ⁄ 综合 ⁄ 共 2812字 ⁄ 字号 评论关闭

数据库范式化是为了最小化冗余和依赖,对关系型数据库中的字段和表进行合理组织的过程。

现在共有1nf,2nf,3nf和bcnf 4种:

http://en.wikipedia.org/wiki/Database_normalization

第一范式是关系型数据库最主要的属性。也就是说第一范式是关系型数据库的最低要求。

如果一个关系型数据库满足第三范式,则称为“范式化的”。关系型数据库满足第三范式就可以了。

有时为了提高数据库的性能会进行反范式化,本文在后面将提到。

第一范式

A relation is in first normal form if the domain of each attribute contains only atomic values, and the value of each attribute contains only a single value from that domain.

即表中每个字段的值是原子的,不可再分的。

例如一个人设计了这样一个客户表:

Customer
Customer ID First Name Surname Telephone Number
123 Robert Ingram 555-861-2025
456 Jane Wright 555-403-1659
789 Maria Fernandez 555-808-9633

之后他意识到一个客户可能有多个电话号码。于是他修改了一下设计:

Customer
Customer ID First Name Surname Telephone Number
123 Robert Ingram 555-861-2025
456 Jane Wright 555-403-1659
555-776-4100
789 Maria Fernandez 555-808-9633

然而,如果电话号码字段是按照普通号码格式来设计的,例如字段长度为12个字符,那么上面的设计就不符合第一范式。事实上,任何一个关系型数据库系统都不允许一个字段存储多个值(注意上面的设计并不是将两个号码存成一个长字符串,而是说一个字段可以存储多个值)。因此我们不可能设计出违背第一范式的数据库。

符合第一范式的设计应该是设计两个表:

Customer Name
Customer ID First Name Surname
123 Robert Ingram
456 Jane Wright
789 Maria Fernandez
Customer Telephone Number
Customer ID Telephone Number
123 555-861-2025
456 555-403-1659
456 555-776-4100
789 555-808-9633


第二范式

表在满足第一范式之后,满足以下条件才能满足第二范式:表中的非关键字段要么依赖于candidate key,要么依赖于另外一个非关键字段。

所谓的candidate key可以理解为行的唯一key。

也就是说如果不满足第一范式,就不可能满足第二范式。

考虑这样一个员工技能表:

Employees' Skills
Employee Skill Current Work Location
Jones Typing 114 Main Street
Jones Shorthand 114 Main Street
Jones Whittling 114 Main Street
Bravo Light Cleaning 73 Industrial Way
Ellis Alchemy 73 Industrial Way
Ellis Flying 73 Industrial Way
Harrison Light Cleaning 73 Industrial Way

Employee字段和Skill字段都不合适作为行key。因为一个特定的员工可能出现多次,而一个特定的skill也可能出现多次。只有Employee和Skill的组合key才能唯一定位一行数据,在该表中只有Employee和Skill的组合key才是candidate key。

剩下的地址字段实际上是被Employee字段决定的。

因此该设计不符合第二范式:非关键字段Current Work Location依赖candidate key的一部分(即Employee)。

不符合第二范式的会带来的问题:

1,数据冗余

上例中很明显,地址信息是重复的。

2,更新异常

假如由于某种原因,修改了Jones的skill为Typing那行对应的地址,但是没有修改另外两种skill对应的地址,数据就出现了不一致。

3,插入异常

如果插入一行Jones的新技能,但是地址不是114 Main Street,则数据出现了不一致。

将上例改为下面的设计则符合第二范式:

Employees
Employee Current Work Location
Jones 114 Main Street
Bravo 73 Industrial Way
Ellis 73 Industrial Way
Harrison 73 Industrial Way
Employees' Skills
Employee Skill
Jones Typing
Jones Shorthand
Jones Whittling
Bravo Light Cleaning
Ellis Alchemy
Ellis Flying
Harrison Light Cleaning


第三范式

下面这个例子满足第二范式,但不满足第三范式。该表存储的数据是几个不同的奖项和每年不同奖项各自的冠军。

Tournament Winners
Tournament Year Winner Winner Date of Birth
Indiana Invitational 1998 Al Fredrickson 21 July 1975
Cleveland Open 1999 Bob Albertson 28 September 1968
Des Moines Masters 1999 Al Fredrickson 21 July 1975
Indiana Invitational 1999 Chip Masterson 14 March 1977

从表中可以得知candidate key是{Tournament,Year},而非关键字段Winner Data of Birth依赖于另一个非关键字段Winner,因此满足第二范式。

但是仍然可以发现有数据冗余,同时可能导致更新异常。

而满足第三范式则可以完全避免这个问题:

Tournament Winners
Tournament Year Winner
Indiana Invitational 1998 Al Fredrickson
Cleveland Open 1999 Bob Albertson
Des Moines Masters 1999 Al Fredrickson
Indiana Invitational 1999 Chip Masterson
Player Dates of Birth
Player Date of Birth
Chip Masterson 14 March 1977
Al Fredrickson 21 July 1975
Bob Albertson 28 September 1968


抱歉!评论已关闭.