【问题标题】:Is it bad to have a table without key?没有钥匙的桌子很糟糕吗?
【发布时间】:2014-03-06 16:05:44
【问题描述】:

我有下表,代表了足球比赛期间给球员的牌:

CREATE TABLE cards (
    player_id INT,
    match_id INT,
    color VARCHAR(4),
    minute INT,

    FOREIGN KEY (player_id) REFERENCES players(id),
    FOREIGN KEY (match_id) REFERENCES matches(id)
);

如您所见,其中没有主键。玩家有可能在同一场比赛中,在同一分钟,收到两张相同颜色的牌。我认为这没问题,因为不需要更精确地知道卡片是在哪一秒发出的。

这是糟糕的设计吗?这个有名字吗?这是任何一种正常的形式吗?

【问题讨论】:

标签: database database-design relational-database database-schema


【解决方案1】:

是的,一般来说,没有主键的表是个坏主意。

其中一个原因是没有主键,如果您想删除或更新其中一条记录(如果您有多个与您解释的数据相同),则无法知道您指的是哪条记录.

例子:

 player_id    match_id      color      minute
 1            100           RED        34
 1            100           RED        34
 2            100           YELLOW     41
 3            200           RED        22

现在,假设您想要更新玩家 1 获得的第二张牌,并将其更改为黄色(或将其移除)。您将如何编写该查询?

因此,如果您希望在同一场比赛中为同一玩家创建多条记录,您可以为每条记录创建一个surrogate key。否则,自然主键将是 player_id 和 match_id 的组合。

CREATE TABLE cards (
    card_id INT PRIMARY KEY,
    player_id INT,
    match_id INT,
    color VARCHAR(4),
    minute INT,

    FOREIGN KEY (player_id) REFERENCES players(id),
    FOREIGN KEY (match_id) REFERENCES matches(id)
);

【讨论】:

  • 我不明白 (player_id, match_id) 如何成为自然主键。
  • @aochagavia - 如果 player_id/match_id 组合自然不同,则将被视为自然键,因为它将唯一地描述记录。
【解决方案2】:

只需添加一个新属性“NumberOfCards”,然后您就可以将 {player,match,colour,minute} 设为关键。

这是糟糕的设计吗?

是的

这是正常的形式吗?

没有。每列都可以为空,并且允许重复的行,因此它不是正确的关系并且不满足任何正常形式。

【讨论】:

    【解决方案3】:

    让我稍微扩展一下sqlvogel said....

    在关系数据库中,“表”是“关系”数学概念的物理表示,是元组的集合。由于它是一个集合(而不是多重集合),它可以包含每个元组最多一次

    没有键的表允许多个相同的行/元组,因此不是关系(您的数据库不能再被视为“关系”)。


    在您的特定情况下,您可以从现有字段中创建一个键,然后添加一个“数量”字段,您可以根据需要递增和递减该字段。或者,考虑使用更“细粒度”的自然键,甚至是“伪代理”键as proposed by Miky Dinescu,这样您就可以真正区分各个卡。

    在极少数情况下,无键表可能有用(当数据不是很“重要”但写入性能很重要时,例如在存储调试跟踪时),但在绝大多数情况下,缺少关键应该是一个大红旗。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-10
      • 1970-01-01
      相关资源
      最近更新 更多