2

您将下面的示例规范化到什么程度,以及该示例到底符合哪个规范化级别?

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, type) 跟踪的单独关系?

4

9 回答 9

2

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

唯一真正节省空间的是电话号码,它的平均宽度为 10 个字符,如果您将其标准化并用 bigint-foreign-reference 替换它,您似乎并没有获得太多收益,但运行时加入:P,然后最重要的是,您需要一个表示电话号码类型的 int。

于 2009-12-07T22:35:19.950 回答
2

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

于 2009-12-07T22:38:23.967 回答
2

因为您已将此系统定义为每种类型只有 0 或 1 个电话号码,所以您的系统比更准确的系统满足更高级别的规范化。

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

同样,您选择将人名分成开头和结尾部分(但忽略前缀、中间名和后缀)。如果您可以将一列分成逻辑部分,那么有人可能会说您没有通过 BCNF。

关于要规范化表的程度,您必须做出的选择主要取决于您选择访问数据的方式。对于大多数人来说,将电话号码之类的列分成多个部分是多余的,但是如果我的上述任何一点似乎对您的需求有用,那么请考虑一下。

PS。什么是 line1 和 line2?

于 2009-12-07T23:10:17.990 回答
1

鉴于你说:

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

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

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

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

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

于 2009-12-07T22:49:42.717 回答
0

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

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

于 2009-12-07T22:36:21.727 回答
0

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

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

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

于 2009-12-07T22:40:20.643 回答
0

为什么不放置一个包含 3 个字段的单独表格:idtype_ofnumber。然后你可以摆脱你的 *_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

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

于 2009-12-07T22:50:59.403 回答
0

我会拆分电话号码 - 出于其他人提到的所有原因,PLUS - 如果您的用户想要通过电话号码搜索,那么使用这种设计编写 sql 将是一个真正的麻烦(假设您想要搜索多种电话号码)。

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

于 2009-12-08T00:14:39.770 回答
0

有人可能会争辩说 zipcode 定义了 (city, state_id),所以这些应该被规范化为依赖列。但是,除非您正在为 USPS 编写应用程序,否则通常不会这样做。与您最初的问题相同 - 拥有 4 条电话记录并不会造成太大伤害,我会保持这种设计。

于 2009-12-10T20:01:31.780 回答