假设,我有一个包含列的表:
- person_id(主键)
- 名
- 姓
- 生日
我对组合 {first_name, last_name} 也有一个唯一约束(我知道更多人可以有相同的名字,但我想让我的示例保持简单)。我想知道这个表是否是第三范式。
我的推理(编辑前):
- 所有字段只能包含原子值,因此表是第一范式。
- 候选键是 1) person_id, 2) [first_name, last_name]
- 唯一的非主要属性是生日。
- 属性生日在功能上不依赖于候选键 1 的一部分(无论如何这是不可能的,因为候选键 1 中只有 1 个属性)
- 属性生日在功能上不依赖于候选键 2 的一部分
- 因此,该表是第二范式。
- 属性生日(是/不是)非传递依赖于候选键 1
- 属性生日不传递依赖于候选键 1
问题(编辑前):
我无法回答的问题是生日是否非传递依赖于 person_id。从功能上讲,这个身份证号码和生日完全没有关系。
- 这是否意味着存在传递依赖(生日取决于 [first_name, last_name],每个组合 [first_name, last_name] 映射到一个 id),因此不在 3NF 中?
- 这是否意味着根本没有依赖关系,因此不在 3NF 中?
- 我是否误解了难懂的语言,这张表是 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。
- 因此,该表是第三范式。