【问题标题】:Second Normal Form/Normalisation confusion: Primary Key? Compound Key?第二范式/规范化混淆:主键?复合键?
【发布时间】:2014-03-27 18:14:50
【问题描述】:

我正在制定一个数据库计划,我对规范化到第二范式有点困惑。我也担心大量的列,我无法正确地弄清楚如何处理它们。

这是我关注的表MatchDetails

想法 1

img link

Player_ID 是另一个表 Users 的唯一主键。 MatchID 是表 Matches 的唯一主键。 Matches 和 Players 之间的关系是多对多的。

这可以用作复合键吗?从某种意义上说,一名球员只能参加一次特定比赛? MatchID 右侧的列是否对复合键有功能依赖,因为它们对于该复合键是唯一的?

想法 2

img link

在此示例中,Participation_ID 是表的唯一主键,因为对于玩家和比赛的各种组合,可以有多个相同的Player_ID 和相同的MatchID 实例。

在这个例子中,我猜这个列是第二范式,因为只有一个主键,匹配值是唯一的,因此在功能上是依赖的?尽管我尝试阅读它here,但我对功能依赖有点困惑。

哦,还有一件小事……

我有点怀疑的最后一件事是大量的列。 MatchID 右侧的所有信息都是有关球员 (Player_ID) 在比赛 (MatchID) 中表现的详细信息。他们应该在另一张桌子上吗?

如果您想查看目前的布局,请链接到其他表格:http://i.imgur.com/52ax04g.png

请忽略 MatchID 没有下划线而其他 ID 有,这只是一个 excel 计划!

【问题讨论】:

    标签: database database-design database-normalization


    【解决方案1】:

    除非同一玩家可以多次参加同一场比赛,否则无论您添加 另一个 键(例如 {Participation_ID} ) 与否。

    添加 {Participation_ID} 键仅在您有一些其他表引用它时才有意义1 并且您希望它们的外键更苗条,或者如果您使用需要非-复合主键。

    MatchID 右边的列是否对复合键有功能依赖

    是的。

    您可以将“函数依赖”简单地视为关系(一组元组)是一个函数的一种方式。要使关系成为函数(在该词的数学意义上),它必须始终为相同的“参数”产生相同的“结果”。

    如果给定键的属性是“参数”而其余属性是“结果”,那么不可能从相同的参数产生两个不同的结果,因为键是唯一的,因此任何关键属性值的特定组合2 不能识别多个元组。

    所以所有属性在功能上总是依赖于键。任何键都是如此,否则它就不是键。

    唯一的问题是某些非关键属性是否依赖于关键属性的正确子集。如果是,则您违反了 2NF。3

    在你的情况下,如果任何属性依赖于 Player_ID 单独(或 MatchID 单独),那将违反 2NF。

    我有点怀疑的最后一件事是大量的列。 MatchID 右侧的所有信息都是有关球员 (Player_ID) 在比赛 (MatchID) 中的表现的详细信息。他们应该在另一张桌子上吗?

    逻辑的角度来看,它们似乎是他们需要的地方。 vertically partitioning 数据不太可能,但可能有一些物理原因。4

    一些不相关的建议:

    • 使用一致的命名:如果有 Player_ID,则应该有 Match_ID,而不是 MatchID(反之亦然)。 哎呀,我错过了你的最后一句话。
    • 对表名使用单数,出于同样的原因,单数通常用于 OOP 中的类名。

    1据我所知,你没有。

    2 又名。 “主要”属性。奇怪的是,主属性不一定属于“主”键(它可以属于备用键),所以说“键属性”可能是一个更好的术语,恕我直言。

    3 显然,这只是复合键的问题,因为如果一个键只有一个属性,它的真子集是空的。

    4 如今,DBMS 通常可以处理数百甚至数千列,而这并不真正符合“大量列”的条件。

    【讨论】:

    • 感谢您的深入回复。我对我的问题感觉更清楚了。如果您看到这一点,我想在我的主要问题之上快速提出一些问题。当我询问将一些数据移动到另一个表时,这是因为在我看来,普遍的共识是“更多行而不是更多列”。考虑到这一点,this 会比将所有数据都放在一张表中更好吗?即使所有这些数据都依赖于同一个复合键。
    • @k4kuz0 好吧,Item_0、Item_1 等是新的 - 它们不在您的原始问题中。这看起来很像 1:N 关系,通常通过单独的表建模。另一方面,1:1 关系通常仅建模为一个表。顺便说一句,我从未听说过“更多行而不是更多列”的共识。我也不明白如何拆分为单独的表删除列 - 如果有的话,您将复制键并创建 more 列,尽管分散在更多表上。
    • Item 1 到 6 代表玩家拥有的槽位(6 个物品槽位),数值代表每个槽位中的物品。有,并且永远只有 6 个项目。不多不少。这不违反 1:N 吗?还是我错了?我明白你对列的意思。所以在那种情况下,我会有一个有 23 列的表,这样可以吗?
    • @k4kuz0 “只有 6 个项目,而且永远只有 6 个项目。” - 在这种情况下,这不是真正的 1:N,你可以保持明确列。 23列就可以了。
    【解决方案2】:

    {PlayerID, MatchID} 列似乎可以用作复合键。

    MatchID 右侧的列确实对(复合)主键有功能依赖,只要它们代表该球员在一场特定比赛中的统计数据。

    如果这些列代表球员的整体统计数据,那么它们仅依赖于 PlayerID,并且这种设计不在 2NF 中。

    普通形式考虑到每个候选键,而不仅仅是主键。在我之前的段落中,您稍后添加一个整数行标识符 ParticipationID 并没有改变 任何东西 - 列 {PlayerID, MatchID} 仍然 似乎是(复合)候选键,您必须将它们考虑在内。

    没有“我没有太多列”这样的正常形式。如果您需要 20 个在功能上依赖于每个候选键的属性,那么您需要 20 个在功能上依赖于每个候选键的属性。

    【讨论】:

    • 非常感谢您的回答! “没有像‘我没有太多列’这样的正常形式。”哈哈这是真的。然而,我已经看到了很多关于有太多专栏的恐怖故事,因此我试图看看如何在它成为问题之前阻止它!我向上述回答者提出了一个问题,如果您有机会,我将非常感谢某人的回复!
    • @k4kuz0 “我看过很多恐怖故事..” - 当您只需要一部分列时,其中一些来自使用 not very flexible 的 ORM .这实际上并不是数据库本身的问题,而是数据库上的工具引入的摩擦。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-27
    • 2011-03-18
    • 1970-01-01
    • 2019-08-30
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    相关资源
    最近更新 更多