Database design 数据库规范化。走向无限和超越?

Database design 数据库规范化。走向无限和超越?,database-design,normalization,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, "

下面的示例的规范化程度到底有多高,以及该示例满足的规范化级别到底有多高

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


由于电话号码定义是一成不变的(没有新的电话号码类型,没有多个家庭电话条目等),我是否有任何理由希望将电话号码拆分为一个单独的关系,由(联系人信息id、电话号码、类型)跟踪?

我不会对其进行规范化。没什么可赚的。我们不再在有8MB内存和32mb硬盘的8位计算机上运行数据库。这是特定于此示例的。复杂的数据结构应该规范化


唯一真正节省空间的是电话号码,它的平均宽度为10个字符,如果您将其标准化,并用bigint外部引用替换它,您似乎不会获得太多,但是运行时连接:p,除此之外,您还需要一个表示电话号码类型的int

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


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

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

是否有任何理由我希望将电话号码拆分为一个单独的关系,由(
联系人信息id
,电话号码,类型)跟踪

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

我想指出的是,地址(第1行和第2行、城市、州和zipcode)也可以规范化,以支持存储个人的家庭、业务地址。我可以有很多避暑别墅…

如果你说:

应该注意的是,每个记录只能有0或1个家庭、手机、工作或传真号码记录

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

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

但后来我处理了几个不同的应用程序,其中只有一个非常需要这种灵活性(不,我们实际上没有做到):这是一所学校的记录。每个联系人记录代表一个人,可以是学生(或前学生)、家长、教师、登录id或其他感兴趣的人中的任何人或所有人。而且,是的,我们有一所学校,我们几乎有所有这些类别的人


然而,在另一个应用程序中,我们不需要这种多样性:软件许可被分配给一个电子邮件地址,从而分配给一个人。有一个邮寄地址与购买和扩展的人,这几乎是它。我们通过电子邮件地址(一个人拥有多个许可证)聚合许可证,然后添加了一种方法来聚合具有多个电子邮件地址的人(一个人拥有多个电子邮件地址)。物理地址与账单信息的联系更加紧密。

为什么不单独设置一个表,其中包含3个字段:idtype\unumber。然后你就可以扔掉你的手机了。比如:

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

我建议对电子邮件也这样做,因为这个人可能在家里有一封电子邮件,在工作时有一封,在其他地方有另一封。

因为你定义了这个系统,每种类型只有0或1个电话号码,所以你的系统比更精确的系统要达到更高的标准化水平

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

同样,您选择将该人的名字分成首个和最后一个部分(但忽略前缀、中间名和后缀)。如果您可以将一列拆分为逻辑部分,则可能会认为您尚未通过BCNF

关于表的规格化程度,您必须做出的选择主要取决于您选择如何访问数据。对于大多数人来说,把电话号码之类的列分成多个部分是多余的,但是如果我上面的任何一点对你的需求有用,那么就考虑一下。
注:第1行和第2行是什么?

出于其他人提到的所有原因,我将电话号码分开,另外,如果您的用户想要按电话号码进行搜索,那么使用这种设计编写sql将是一件非常麻烦的事(假设您想要跨多种类型的电话号码进行搜索)


在“联系人信息”表中,用户很可能希望进行这种类型的搜索。

有人可能会认为zipcode定义了(城市、州_id),因此这些应该按照