数据库规范化。超越无限?

时间:2009-12-07 22:32:04

标签: database-design normalization

您对下面示例的规范化程度究竟有多远,以及此示例确实符合哪个规范化水平?

CREATE TABLE "public"."contact_info" (
  "id" SERIAL, 
  "home_phone" TEXT, 
  "mobile_phone" TEXT, 
  "work_phone" TEXT, 
  "fax_phone" TEXT, 
  "email" TEXT, 
  "line1" TEXT, 
  "line2" TEXT, 
  "city" TEXT, 
  "state_id" INTEGER, 
  "zipcode" TEXT, 
  "preferred_type" TEXT, 
  "first_name" TEXT, 
  "last_name" TEXT,
  CONSTRAINT "contact_info_pkey" PRIMARY KEY("id"), 
  CONSTRAINT "contact_info_fk_state_id" FOREIGN KEY ("state_id")
    REFERENCES "public"."states"("id")
    ON DELETE NO ACTION
    ON UPDATE NO ACTION
    NOT DEFERRABLE
) WITH OIDS;

应该注意的是,每条记录只能有0或1个家庭,移动,工作或传真号码记录。每个电话号码在功能上完全取决于我的主键。根据我对数据库规范化的了解,我认为这符合5NF,但是6NF失败了。

由于电话号码定义是一成不变的(没有新的电话号码类型,没有多个home_phone条目等),我是否有理由将电话号码分成跟踪的单独关系(contact_info_id,phone_number ,键入)?

9 个答案:

答案 0 :(得分:2)

我不会将它标准化。没有什么可以获得的。我们不再在8位计算机上运行数据库,只有8 mb的ram和32mb的硬盘驱动器。这是特定于此示例的。复杂的数据结构应该规范化。

唯一真正的空间保护程序是电话号码,平均10-char宽,如果你将其标准化并用bigint-foreign-reference替换它,你似乎没有获得太多但运行时加入:P ,最重要的是你需要一个代表电话号码类型的int。

答案 1 :(得分:2)

表设计的一般经验法则是:如果您希望表对某些列包含很高百分比的NULL值,那么这些列可能应该在单独的表中。无论如何,如果您不希望出现性能问题,那么非规范化设计可能没问题,并且在维护数据库时它可以帮助您。

答案 2 :(得分:2)

由于您已将此系统定义为每种类型只有0或1个电话号码,因此您的系统正在达到比更准确的系统更高的标准化水平。

就个人而言,我会将电话号码存储在一个单独的表中,其中包含id,公共ID,类型,区号,交换,后缀和扩展名。如果您需要使用这些值中的某一个选择all,那么在SQL中以编程方式执行会更加痛苦。

以同样的方式,你选择将这个人的名字分成第一个和最后一个部分(但忽略了前缀,中间名和后缀)。如果你可以将一列拆分为逻辑部分,可以说你没有通过BCNF。

您需要做出的关于规范化表格的距离的选择主要取决于您选择如何访问数据。对于大多数人来说,将电话号码等栏目分成多个部分是过度的,但如果我的上述任何一点似乎对您的需求有用,那么请考虑一下。

PS。什么是line1和line2?

答案 3 :(得分:1)

鉴于你说:

  

应该注意的是,每条记录只能有0或1个家庭,移动,工作或传真号码记录。

...然后您的表格设计是一个很好的匹配,因为它将所有这些数据值紧密绑定到此联系人记录。

根据应用程序的不同,我可以提出一种更灵活的设计,其中联系人可以有多个不同类型的地址,多个不同类型的电话号码和多个电子邮件地址用于不同目的甚至多个电话号码和/或电子邮件地址一个地址。

但后来我开始研究几种不同的应用程序,其中只有一种非常需要这种灵活性(不,我们实际上没有实现):这是学校的记录。每个联系人记录代表一个人,可以是学生(或前学生),父母,教师,登录ID或其他感兴趣的人中的任何一个或全部。而且,是的,我们有一所学校,我们几乎有所有这些类别的人!

然而,在另一个应用程序中,我们不需要这种多样性:软件许可证被分配到电子邮件地址,因此分配给一个人。有一个邮件地址与购买相关联,并且通过扩展该人,这就是它。我们通过电子邮件地址(一个人拥有多个许可证)汇总了许可证,后来添加了一种方法来聚合具有多个电子邮件地址的人(一个人拥有多个电子邮件地址)。物理地址与计费信息的联系更紧密。

答案 4 :(得分:0)

我要指出的一点是,使用TEXT列有点浪费,为什么不使用VARCHAR?

规范化的一个优点是减少了重复验证的代码。您预计未来变化的另一个地方是您是否需要添加第二个地址(我们这里有工作电话,但地址被假定为家庭地址?)。

答案 5 :(得分:0)

  

我有什么理由想将电话号码拆分为由(contact_info_id,phone_number,type)跟踪的单独关系?

业务规则更改的可能性,以允许多个数字类型与特定人员相关联。如果您对表格进行标准化,则只需调整约束条件即可。支持代码以适应变化几乎没有变化。在当前形式中,您将有一个主要的数据模型更改和随后的应用程序更改 - 非常昂贵。

我想指出地址(第1行和第2行,城市,州和邮政编码)也可以标准化,以支持存储人员家庭,商业地址。我可以有很多避暑别墅......

答案 6 :(得分:0)

为什么不将包含3个字段的单独表格放入: id type_of 即可。然后你可以摆脱你的* _phone的东西。类似的东西:

id      type_of      number
1       home         222 11 22
1       work         312 12 12
2       mobile       345 23 23
2       home         233 65 23
2       work         945 30 19

我会对电子邮件做同样的事情,因为这个人可以在家里收到一封电子邮件,一封在工作中,另一封在其他地方。

答案 7 :(得分:0)

我分出了电话号码 - 由于其他人提到的所有原因,加上 - 如果你的用户想要通过电话号码搜索,用这种设计编写sql将是一个真正的麻烦(假设你想要的话)搜索多种类型的电话号码。)

在“联系信息”表格中,用户很可能想要进行此类搜索。

答案 8 :(得分:0)

有人可能会说zipcode定义了(city,state_id),所以那些应该被归一化为依赖列。但是,除非您正在为USPS编写应用程序,否则通常不会这样做。 与你原来的问题相同 - 拥有4个电话记录并没有太大的伤害,我会以这种方式保留设计。