注意:问题已更新。查看编辑修订以查看原始问题。
情景。目前,一家动物慈善机构通过电子表格跟踪其机构的成本,如下所示:
[已删除损坏的图片链接]
1NF:
上表已经在 1NF 中,因为它遵守 1NF 的定义。
第一范式:每行和列的交集包含一个且仅一个值的关系。
在阅读了 Catcall 的回答后,我可以看到我搞砸了我的依赖关系。我最初所做的一切就像猫叫说的一样!添加了一个主键列,并对自己说“那里,解决了这个问题!”
所以很明显这是错误的。我现在已经更仔细地阅读了函数依赖,在我拥有的这本书中,它将它们定义为:
功能依赖:描述关系中属性之间的关系。例如,如果 A 和 B 是关系 R 的属性,并且 B 在功能上依赖于 A(由 A --> B 表示),如果 A 的每个值都与 B 的一个值相关联,则存在功能依赖。
牢记上述定义,并检查我现在扩展的(更多数据)示例表,我可以看到 PetHouse Ltd 并不总是与 Dog food 相关联,这打破了关于 A 与 EXACTLY one 相关联的定义部分B 的价值。
所以我想实际上我在识别我的功能依赖项时被困在这里。在这里,我有点不知所措,因为我从未使用过由三个不同列组成的复合键,但无论如何我都会继续前进,看看我能到达哪里。
Catcall 建议使用 3 列 [ Name, BoughtFrom, TimeBought ] 作为数据标识符(即由 3 列组成的表的复合键),这是有道理的,因为这将唯一标识表中的每一行数据。所以关系的符号变为:
IncuredCosts (名称, BoughtFrom , TimeBought , 成本)
我拥有的这本书也有一个有趣的部分,关于我们需要进行规范化的函数依赖。它指出我们所追求的功能依赖必须具有以下特征:
- 左侧(行列式)的属性与函数依赖右侧的属性之间存在一对一的关系。(注意,相反方向的关系可以是一对一或一对多的关系。)
- 他们一直持有。
- 行列式具有维持与右侧属性的依赖关系所需的最少属性。换句话说,依赖关系左侧和右侧的属性之间必须存在完整的功能依赖关系。
我相信上述所有特征都适用于这种功能依赖:
(名称、BoughtFrom、TimeBought)-> 成本
现在,传递依赖,在书中(可能像 Catcall 所说的那样是错误的)被定义为:
传递依赖:一个条件,其中 A、B 和 C 是关系的属性,如果 A --> B 和 B --> C,则称 C 通过 B 传递依赖于 A(前提是 A 在功能上不是取决于 B 或 C)。
我认为我之前定义的关系没有任何传递依赖关系是否正确?但是话又说回来,如果是这样的话,那就意味着我已经达到了 3NF!显然,3NF 的主要步骤是将传递依赖关系移除到它们自己的关系中。
我真的达到了3NF吗?
顺便谢谢你。通过这篇文章我学到了很多东西。
是的,它在 1NF 中。
您不能通过在表格末尾挂一个数字并说“那里。我有一个主键”来回避确定所有候选键的艰巨工作。该表的一个自然候选键是{Name, Buy from, Date purchase}。考虑使用“购买时间”而不是“购买日期”。
您对 2NF 的定义是错误的。代替
你需要更多这样的东西。
第二范式:处于第一范式的关系,每个非主属性在功能上完全依赖于每个候选键。
术语非主属性并不完全意味着非主键属性的含义。
您对 3NF 的定义是错误的,并且与您对 2NF 的定义错误的原因相同。
而不是这个
你需要更接近这个的东西。
第三范式:处于第二范式的关系,其中每个非主属性都非传递地依赖于每个候选键。(没有一个很好的方法可以用一句话表达所有这些否定。)
确定您的表是否在 3NF 中的关键是传递依赖关系。要弄清楚你是否有这些,最好的问题是:
如果我更改 x 列中的值,这是否意味着我也必须更改 y 列中的值?
对于所有非主列。如果答案是肯定的,那么您不在 3NF 中。
在这种情况下,您必须对
name
和bought_from
列回答“是”。如果第三行是狗粮而不是汽油,那也意味着您必须换成bought_from
英国汽油以外的人。要将其纳入 3NF,您需要一个单独的
products
表,其中列出了产品名称和供应商。然后,您将拥有一个外键 fromincurred_costs
到这个新表的主键。首先,在我看来,您正在建立一个会计数据库。我只是建议您重新考虑或查看现有的开源数据库(例如,我维护 LedgerSMB)。
其次,关于规范化,您需要额外的表格。你应该把你买的东西和你从谁买的东西分开到其他表中,然后有一个表,或多或少地记录你在这里的信息,但带有其他表的键,作为一个极简的解决方案。所以像(对不起这里的 PostgreSQL 主义):