数据库设计和规范化

Posted

技术标签:

【中文标题】数据库设计和规范化【英文标题】:Database Design and Normalization 【发布时间】:2011-07-25 05:48:59 【问题描述】:

我正在 VB.NET 中开发类似“AddressBook”的项目。在 SQL Server2005 中开发数据库时,我希望遵循规范化的原则,并尽可能保持其规范化程度。

我正在使用的字段是这些。

Create table AddressBook_Contact
(
Contact_ID int Primary Key,FirstName varchar(15),MiddleName varchar(15),LastName varchar(15),BirthDay datetime,HomeCountry varchar(20),HomeState varchar(20),HomeCity varchar(20),HomeMobile varchar(40),HomePhone varchar(40),HomeMobile varchar(40),HomeFax varchar(40),HomeZipCode varchar(10),HomeEmail varchar(50),HomeAddress text, 
BusIndustry varchar(20),BusCompany varchar(20),BusWebsite varchar (30),BusCountry varchar(20),BusState varchar(20),BusCity varchar(20),BusMobile varchar(40),BusPhone varchar(40),BusFax varchar(40),BusZipCode varchar(10),BusEmail varchar(50),
BusAddress text,Note text
)

如果我在一个表中创建所有字段..是否违反规范化?以及对表的影响是什么,除了由于时间大幅增加而变得缓慢之外。

如果我为 Contact(Biodata,HomeInfo,BusinessInfo) 创建单独的表

create table AddressBook_Bio
(
BookID int Primary Key,
Title varchar(15),
FirstName varchar(15),
SecondName varchar(15),
LastName varchar(15),
BirthDay datetime,
Note text
)

create table AddressBook_Home
(
'My question in this case is should i declare BookID as foreign key or primary key to the table and why?'
FOREIGN KEY (BookID) REFERENCES AddressBook_ContactBio(BookID),
HCountry varchar(20),
HState varchar(20),
HCity varchar(20),
HMobile varchar(40),
HPhone varchar(40),
HFax varchar(40),
HZipCode varchar(10),
HEmail varchar(50),
HAddress text
)

create table AddressBook_Business
(
same issue as "AddressBook_Home"
)

感谢您关心表达和分享您的意见和知识。

【问题讨论】:

【参考方案1】:

是的,我相信您要创建的大表没有标准化。它可能产生的影响是您的表中可以有 NULL 值,这会浪费空间。

我认为您可能希望将 BookID 声明为主键,因为它似乎是该表的唯一键,并且每个表都提供了一个人的不同信息。这类似于部分重叠的子类。

【讨论】:

这个解决方案看起来很公平......但它使编码有点困难,但真的很安全......我会用这个......谢谢【参考方案2】:

如果只有一个家庭地址和一个公司地址,那么第一个结构并不是真正“反对规范化”——它是在表达数据的结构。

如果您想允许多个地址(1、2 或更多,甚至为零),您应该创建一个单独的地址表(可能带有一个“类型”列,说明它是家庭地址、公司地址还是其他地址)。

您给出的 2 个几乎相同的地址表的想法似乎是一种不好的方法,因为一个表就足够了,而且您不需要复制和粘贴来创建两个相同的表。

如果你创建一个Address表,它应该有BookID作为外键,它也应该有自己独立的主键。

您想知道 BookID 是否应该是 *_Address 表上的主键这一事实表明,您将某些内容拆分为 2 个表,而实际上它应该是一个。

【讨论】:

【参考方案3】:

始终可以实现的最高范式是6NF。简而言之,6NF 中的表将有一个键(可能包含多个列)加上最多一个附加属性(请注意,属性可能有亚原子元素,每个元素都有自己的列,例如地址有亚原子元素 zipcode、state、country、等等)。因此,至少您应该为 Note、HMobile、HPhone、HFax、HEmail 和 Note 设置不同的表,如果它不是密钥的一部分,则可能是 BirthDate(我认为它是)。

【讨论】:

不确定您所说的“亚原子元素”是什么意思。您是在谈论关系值属性/嵌套表吗? 这里有很好的信息,但对于 OP 来说太过分了。 @dportas:考虑具有employee_numberfamily_namegiven_name 的属性的EmployeeNames。我认为这是在 6NF 中,因为 family_namegiven_name 是元素“employee_name”的两个亚原子粒子(Celko 使用这个短语),出于实际目的,它们通常被分开存储。 @Dane:OP 在他们的规范中明确声明,“我想......尽可能保持其标准化程度”。 @onedaywhen,如果 family_name 和 given_name 是 EmployeeNames 中的两个非主属性,那么 EmployeeNames 不可能在 6NF 中,因为它可以被无损分解。来自“关系数据库词典”:“Relvar R 是第六范式,6NF,当且仅当它不能被无损分解,除了平凡——即,当且仅当它满足的唯一 JD 是平凡的那些。”

以上是关于数据库设计和规范化的主要内容,如果未能解决你的问题,请参考以下文章

MaxCompute 表(Table)设计规范

数据库设计和规范化

MySQL 设计与开发规范

数据库设计简明指导与规范

软考 系统架构设计师案例分析⑦ 数据库规范化与反规范化

MySQL数据库设计规范