代码之家  ›  专栏  ›  技术社区  ›  Kenaniah

数据库规范化。到无穷远?

  •  2
  • Kenaniah  · 技术社区  · 15 年前

    您到底规范化下面的示例有多远,以及这个示例到底符合哪一个规范化级别?

    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。

    由于电话号码定义设置为Stone(没有新的电话号码类型,没有多个家庭电话条目等),是否有任何理由要将电话号码拆分为跟踪的单独关系(联系人信息、电话号码、类型)?

    9 回复  |  直到 15 年前
        1
  •  2
  •   Nick Vaccaro    15 年前

    由于您已将此系统定义为每种类型只有0或1个电话号码,因此您的系统将达到比更精确的系统更高的规范化级别。

    就个人而言,我会将电话号码存储在一个单独的表中,表中包含ID、公共ID、类型、区号、交换、后缀和扩展名。如果您需要选择所有具有这些值中某一个的值,那么在SQL中进行编程会更加困难。

    同样地,你也选择了将这个人的名字分成第一部分和最后一部分(但是忽略了前缀、中间名和后缀)。如果您可以将一列分解为逻辑部分,则可能会认为您没有传递bcnf。

    关于要规范化表的程度,您必须做出的选择主要取决于您选择如何访问数据。对大多数人来说,把电话号码这样的一列分成多个部分太过分了,但是如果我上面的任何一点对你的需求似乎有用,那么考虑一下。

    第1行和第2行是什么?

        2
  •  2
  •   Hassan Syed    15 年前

    我不会使它正常化。没有什么可以得到的。我们不再在8位计算机上运行数据库,8 MB内存和32 MB硬盘。这是特定于此示例的。复杂的数据结构应该规范化。

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

        3
  •  2
  •   Konamiman    15 年前

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

        4
  •  1
  •   staticsan    15 年前

    假设你说:

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

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

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

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

    然而,在另一个应用程序中,我们不需要这种多样性:一个软件许可被分配到一个电子邮件地址,从而分配给一个人。有一个与购买相关联的邮寄地址,扩展来说就是那个人,差不多就是这个地址。我们按电子邮件地址(一个人拥有多个许可证)聚合许可证,后来又添加了一种方法来聚合拥有多个电子邮件地址(一个人拥有多个电子邮件地址)的人。物理地址与账单信息的绑定更加紧密。

        5
  •  0
  •   MattMcKnight    15 年前

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

    标准化的一个优势是减少用于验证的代码重复。另一个您预计未来变化的地方是,如果您需要添加第二个地址(我们这里有工作电话,但地址假定为家庭地址?).

        6
  •  0
  •   OMG Ponies    15 年前

    我有什么理由要把电话号码分割成一个单独的关系( contact_info_id ,电话号码,类型?

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

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

        7
  •  0
  •   user224243    15 年前

    为什么不放一个有三个字段的单独表格: 身份证件 , Ⅲ型 . 然后你就可以把你的手机扔掉了。类似:

    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
    

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

        8
  •  0
  •   Sylvia    15 年前

    我会把电话号码分开——出于其他人提到的所有原因,再加上——如果你的用户想按电话号码搜索,那么用这种设计编写SQL(假设你想搜索多种类型的电话号码)将是一件非常麻烦的事。

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

        9
  •  0
  •   SergeyKazachenko    15 年前

    有人可能会说zipcode定义了(city,state_id),所以应该将它们规范化为依赖列。但是,除非您正在为USPS编写应用程序,否则通常不会这样做。 和你原来的问题一样-有4个电话记录不会有太大的伤害,我会保持这样的设计。