2

假设,我有一个包含列的表:

  • person_id(主键)
  • 生日

我对组合 {first_name, last_name} 也有一个唯一约束(我知道更多人可以有相同的名字,但我想让我的示例保持简单)。我想知道这个表是否是第三范式。


我的推理(编辑前):

  • 所有字段只能包含原子值,因此表是第一范式。
  • 候选键是 1) person_id, 2) [first_name, last_name]
  • 唯一的非主要属性是生日。
  • 属性生日在功能上不依赖于候选键 1 的一部分(无论如何这是不可能的,因为候选键 1 中只有 1 个属性)
  • 属性生日在功能上不依赖于候选键 2 的一部分
  • 因此,该表是第二范式。
  • 属性生日(是/不是)非传递依赖于候选键 1
  • 属性生日不传递依赖于候选键 1

问题(编辑前):

我无法回答的问题是生日是否非传递依赖于 person_id。从功能上讲,这个身份证号码和生日完全没有关系。

  1. 这是否意味着存在传递依赖(生日取决于 [first_name, last_name],每个组合 [first_name, last_name] 映射到一个 id),因此不在 3NF 中?
  2. 这是否意味着根本没有依赖关系,因此不在 3NF 中?
  3. 我是否误解了难懂的语言,这张表是 3NF 中的吗?

我的推理(编辑后):

  • 如果你知道 person_id,你就知道他的名字、姓氏和他的生日,所以有 FD {person_id} -> {first_name}、{person_id} -> {last_name} 和 {person_id} -> {birthday}。
  • 如果你知道一个人的名字和姓氏,你就知道他的 person_id 和生日,所以有 FD {first_name, last_name} -> {person_id} 和 {first_name, last_name} -> {birthday}。
  • 如果您知道一个人的生日,那么您对他的 person_id 或姓名一无所知,因此没有从生日到另一个(一组)属性的 FD。

  • 所有字段只能包含原子值,因此表是第一范式。

  • 候选键是 1) {person_id}, 2) {first_name, last_name}
  • 唯一的非主要属性是 {birthday}。
  • {birthday} 属性在 CK 1 的一部分上不是 FD(无论如何这是不可能的,因为 CK 1 中只有 1 个属性)
  • 属性 {birthday} 在 CK 2 的一部分上不是 FD
  • 因此,该表是第二范式。

  • 有一个 FD {person_id} -> {birthday},所以属性 {birthday} 是非传递依赖于 CK 1

  • 有一个 FD {first_name, last_name} -> {birthday},所以属性 {birthday} 非传递依赖于 CK 2
  • 因此,该表是第三范式。

有一个依赖 {person_id} -> {first_name, last_name} -> {birthday},但由于还有一个直接依赖 {person_id} -> {birthday},所以这个依赖不是传递的。

问题(编辑后):

我没有从书中预定义的一组 FD,所以我不确定 FD 是否正确。有人可以确认这一点,或者如果他们看起来不正确,请展示我如何在这个实际示例中找到 FD?


第三个推理(第二次编辑):

FD:

  • 如果你只知道一个人的person_id,你就知道他的名字、姓氏和他的生日(不能有多个人具有相同的person_id)
    • FD:{person_id} -> {first_name}
    • FD:{person_id} -> {last_name}
    • FD:{person_id} -> {birthday}
  • 不再需要考虑包含 {person_id} 的超集
  • 如果你只知道一个人的名字,你就不知道这个人的任何其他字段(可以有多个人的名字相同)
    • 不是 FD:{first_name} -> {person_id}
    • 不是 FD:{first_name} -> {last_name}
    • 不是 FD:{first_name} -> {birthday}
  • 如果您只知道一个人的姓氏,则您不知道此人的任何其他字段(可以有多个具有相同姓氏的人)
    • 不是 FD:{last_name} -> {person_id}
    • 不是 FD:{last_name} -> {first_name}
    • 不是 FD:{last_name} -> {birthday}
  • 如果你只知道一个人的生日,你不知道这个人的任何其他字段(可以有多个人的生日相同)
    • 不是 FD:{birthday} -> {person_id}
    • 不是 FD:{birthday} -> {first_name}
    • 不是 FD:{birthday} -> {last_name}
  • 如果你知道一个人的 first_name 和 last_name,你就知道他的 person_id 和他的生日(不能有多个人具有相同的 first_name 和 last_name)
    • FD:{first_name, last_name} -> {person_id}
    • FD: {first_name, last_name} -> {birthday}
  • 不再需要考虑包含 {first_name, last_name} 的超集
  • 如果您知道一个人的名字和生日,则您不知道此人的任何其他字段(可能有多个人的名字和生日相同)
    • 不是 FD:{first_name,birthday} -> {person_id}
    • 不是 FD:{first_name,birthday} -> {last_name}
  • 如果您知道一个人的姓氏和生日,则您不知道此人的任何其他字段(可以有多个具有相同姓氏和生日的人)
    • 不是 FD:{last_name,birthday} -> {person_id}
    • 不是 FD:{last_name,birthday} -> {first_name}

正常形式:

  • 所有属性只能包含单个值,因此表是第一范式。

  • 查看 FD,有两个候选键:1) {person_id}, 2) {first_name, last_name}

  • 唯一的非主要属性是 {birthday}。
  • {birthday} 属性在 CK 1 的一部分上不是 FD(无论如何这是不可能的,因为 CK 1 中只有 1 个属性)
  • 属性 {birthday} 在 CK 2 的一部分上不是 FD(即没有 FD {first_name} -> {birthday} 或 FD {last_name} -> {birthday})
  • 因此,该表是第二范式。

  • 当存在满足 S -> X 和 X -> T 而不是(X -> S)的 X 时,S 可传递地确定 T

  • 让 S = CK1 = {person_id} 和 T = {birthday}。当 X = {first_name, last_name} 时,唯一的 X 使得 S -> X 和 X -> T。然而,那么 X -> S 也成立。因此,S 非传递地确定 T。
  • 让 S = CK2 = {first_name, last_name} 和 T = {birthday}。当 X = {person_id} 时,唯一的 X 使得 S -> X 和 X -> T。然而,那么 X -> S 也成立。因此,S 非传递地确定 T。
  • 因此,该表是第三范式。
4

1 回答 1

3

回复你原来的问题:

你的组织和推理不健全。首先给出所有的FD。例如,这确定了CK。例如,您不能仅仅给出(所谓的)CK(暗示某些 FD)和几个非 FD。例如,在不知道所有 FD 的情况下无法确定“非传递依赖”。只有这样你才能写出正确的项目符号并回答你编号的问题。

但是让我们假设 {first_name,last_name} 和 {person_id} 确实是唯一的 CK,并且除了每个 CK 确定不在其中的每个属性这一事实所暗示的那些之外,没有任何 FD。

从功能上讲,这个身份证号码和生日完全没有关系。

我不知道您所说的“从功能上讲,两者之间根本没有关系”。也许您想说 {person_id} 在功能上不能确定 {birthday}。但它确实如此,因为 CK 确定了所有不在其中的属性。也许您的意思是您没有看到人员 ID 和生日之间的应用程序约束和/或涉及表的 person_id 和生日值的表约束。但是有:给定的人一次只有一个生日,而在表中 person_id 一次只有一个生日。这是“人”、“生日”、person_id 和生日的含义和规则的结果。person_id 和birthday 的约束用“{person_id} -> {birthday}”表示

当存在满足 S -> X 和 X -> T不是(X -> S)的 X 时,S 可传递地确定 T。当 S 不传递地确定 T 时,S 非传递地确定 T。

  1. 这是否意味着存在传递依赖(生日取决于 [first_name, last_name],每个组合 [first_name, last_name] 映射到一个 id),因此不在 3NF 中?

我不知道“每个组合都映射到一个 id”是什么意思,更不用说为什么它暗示非 3NF 了。也许您想说将 {person_id} 作为 S 将 {birthday} 作为 T 并将 {first_name, last_name} 作为 X 我们有 S -> X 和 X -> T 所以(错误地)非素数属性是传递依赖的在 CK 上,所以关系不在 3NF 中。但是你没有满足 not(X -> S)。

对于 {person_id} 作为 S 和 {birthday} 作为 T 的唯一可能性 X -> T 有 {first_name,last_name} 作为 X 但 X -> S 因为 X 是一个键,所以 S -> T 不是传递的。

同样,对于 {first_name,last_name} 作为 S 和 {birthday} 作为 T,X -> T 的唯一可能性是 {person_id} 作为 X 但 X -> S 因为 X 是一个键,所以 S -> T 不是传递的。

  1. 这是否意味着根本没有依赖关系,因此不在 3NF 中?

由于 2NF 中的关系和每个非主属性都非传递地依赖于每个 CK,因此该关系在 3NF 中。

  1. 我是否误解了难懂的语言,这张表是 3NF 中的吗?

你没有声称它是或不是,是吗?

(请编辑您的问题以使用正确的技术术语。)

重新编辑您的版本

(你在评论中承认你的最后一个子弹应该有 CK 2 并且它是不健全的。而且我对你不清楚的措辞的猜测或多或少是你的意思。)

  • 所有字段只能包含原子值,因此表是第一范式。

规范化只对关系“表”有意义,即关系。这意味着唯一的无序属性(“列”)和元组(“行”)。每个元组每个属性一个值。所有关系都在 1NF 中。

关系表总是在 1NF 中。行的每一列都有一个列类型的值。非关系数据库被“规范化”为表,即 1NF(“规范化”的第一意义上),它摆脱了重复组。然后这些表/关系被“规范化”为更高的规范形式(“规范化”的第二种意义)。

“原子”没有帮助:“原子”最初意味着不是关系。

Codd 1970 年的原始论文中,他解释说“原子”不是关系(即不是表):

到目前为止,我们已经讨论了在简单域上定义的关系示例——其元素是原子(不可分解)值的域。可以在关系框架内讨论非原子值。因此,某些域可能具有作为元素的关系。

到 Codd 1990 年出版《数据库管理的关系模型:第 2 版》一书时:

从数据库的角度来看,数据可以分为两种类型:原子数据和复合数据。

在关系模型中只有一种复合数据:关系。

关系是单个值,因此关系值属性没有任何问题。(佩斯·科德(Pace Codd)对此改变了看法。)

  • 候选键是 1) {person_id}, 2) {first_name, last_name}
  • 唯一的非主要属性是 {birthday}。

要规范化,您必须知道每个属性子集的属性(非平凡)在功能上依赖于它。尽管行列式的每个超集都决定了它的作用,但它处理了很多。你跳过了那一步。

你不能证明 {first_name,last_name} 是一个 CK,而不表明 {first_name} 和 {last_name} 不是通过各自确定的 CK。假设你这样做了,你仍然不会考虑剩余的可能决定因素 {first_name,birthday} 和 {last_name,birthday}。

在您证明没有其他 CK 之前,您无法证明这些是唯一的 CK。您必须为每个属性子集显示它是否是 CK。虽然没有 CK 的超集是 CK,但它照顾了很多。有算法。

  • 有一个 FD {person_id} -> {birthday},所以属性 {birthday} 是非传递依赖于 CK 1
  • 有一个 FD {first_name, last_name} -> {birthday},所以属性 {birthday} 非传递依赖于 CK 2

您新的最后两个项目符号是不合理的。看看我的消息对“(非)传递依赖”的定义和使用;只知道 S -> T 并不能告诉你足够的信息。当存在非传递 FD S -> X -> T 时,它也必须是 S -> T;因此,仅知道 S -> T 并不能告诉您 S 是传递还是非传递决定 T。“->”并不意味着“直接”;非传递性是“直接”唯一有意义的概念。

也许“所以”是指“这两种情况中的第一种情况如下所示”?

有一个依赖 {person_id} -> {first_name, last_name} -> {birthday},但由于还有一个直接依赖 {person_id} -> {birthday},所以这个依赖不是传递的。

见上文:“直接”是一种误解。正如我在原始答案中所说的那样,CK1 的 {first_name, last_name} -> {person_id} 和 CK 2 的 {person_id} ->{first_name, last_name} 。

我没有从书中预定义的一组 FD,所以我不确定 FD 是否正确。有人可以确认这一点,或者如果他们看起来不正确,请展示我如何在这个实际示例中找到 FD?

由于可能出现的每种可能的应用情况以及将行放入表中与将行排除在外的标准(谓词),您必须考虑该表可能具有的每个值。您可能会想到假定 FD 的反例,其中两行可以共享假定行列式的相同值。例如,对于 {first_name,birthday} 和 {last_name,birthday},您可以期望两个不同的人具有相同的姓名和生日。(您可以检查最后两个假定的 FD。)

(现在您的语言更清晰了。粗略地说,您的错误(仍然)来自不使用定义和跳过步骤。)

重新您的第二个编辑版本:

现在看起来你可能已经做好了一切。(虽然我不能确定,因为你没有明确说明没有更多的 2 元素属性集并且没有更多的属性集;为什么那对是 CK 的集合;以及 2NF/3NF “因此。)

像“如果你知道一个人的姓氏和生日,你不知道这个人的任何其他领域”这样的措辞是有问题的。我:如果我只知道两个领域,我当然不知道其他领域;所以从来没有FD?你:对于一个人。我:但是如果我认识这个人,那么我就知道他们的名字;所以有FD吗?你:如果你知道一个人的名字和生日,但不知道谁;你不知道任何其他领域。我:有时我确实知道其他领域;所以暗示是错误的;所以有FD吗?事实证明,“知道”是一个非常容易混淆的词,最好避免。写,“鉴于......存在......”。正如您在“(不能有多个...)”中所做的那样。

于 2014-11-29T03:18:47.793 回答