我正在为所有 Magic the Gathering 卡片创建一个数据库...卡片表如下所示:
- 卡号
- 姓名
- 文本
- 稀有ID
- 颜色ID
- 版本号
- 其他栏目...
同一张卡片可以出现在多个版本中,并且在某些独特的情况下,在不同的版本中它会有不同的稀有度。
我知道如何做到这一点的唯一方法是为卡片出现的每个版本创建一个新卡片条目。但有时同一张卡片出现在 10 多个版本中而没有任何变化(至少与该数据库相关的内容没有),我会创建很多不必要的条目。
有更好的解决方案吗?
我正在为所有 Magic the Gathering 卡片创建一个数据库...卡片表如下所示:
同一张卡片可以出现在多个版本中,并且在某些独特的情况下,在不同的版本中它会有不同的稀有度。
我知道如何做到这一点的唯一方法是为卡片出现的每个版本创建一个新卡片条目。但有时同一张卡片出现在 10 多个版本中而没有任何变化(至少与该数据库相关的内容没有),我会创建很多不必要的条目。
有更好的解决方案吗?
根据评论中的反馈,这是我的建议(它仍然可能会错过更改,但我认为这是一个公平的开始)。确保捕获域模型中的所有内容!以后更改数据很容易..如果有的话。
卡片 |-这些卡片在所有版本中都是通用的* CardId、CardName、DeckColor、.. |-PK-| |-可能的钥匙?-| 版本 版本 ID、版本名称、发布日期、.. |-PK-| |-钥匙?-| CardEditions |-这些是每个卡/版本唯一的 CardId,EditionId,稀有度,规则,.. |-PK-| |-FK-| |-FK-|
(*Bill Karwin 指出有多种颜色的卡片,arg!为了满足这个要求,浮动 CardsColors 关系,就像 CardEditions 一样。如果颜色也跨版本发生变化,那我只想哭..)
我在上面列出了一个简单的模式(可以说没有完全规范化)。但是,为了进一步阅读,请查看“减缓数据变化”,因为有几种不同的方法来处理它。
评论更新:
如何找到特定版本的卡片,假设我们知道卡片名称和版本名称:
SELECT * FROM Cards c
JOIN CardEditions ed
on ed.cardId = c.cardId
JOIN Edition e
on e.editionId = ed.editionId
WHERE c.cardName = 'Some Awesome Card'
AND e.editionName = 'Ultimate'
请注意,如果将 CardName 和 EditionName 用作主键 (PK) 并在相应的 FK 中使用 - 而不是代理 CardId/EditionId - 那么我们可能完全避免了连接。关于哪种方法更好,存在很大的争论。我使用代理键来避免复合 PK,除非在连接表(例如 CardEditions)中,因为我喜欢让查询更简单。但是,这仍然使用/拥有 EditionId 代理键..
可能的键(或“键?”)意味着我怀疑这个字段也应该被视为一个键 - 它应该应用一个唯一约束(可能还有索引)。一个关系可以有多个 Key,其中一个 Key 是唯一标识一条记录所需的一组列。主键只是通常用于此目的的“选定”键。
请注意,这个模型并没有完全标准化,因为一个关系有多个 Key;但是,我发现与代理键保持一致并定义次要约束是最有效的。这也是因为我喜欢将记录视为驱动模型的实体。
了解 MySQL 是一个关系数据库,并且要正确利用其功能,您需要将对象关联在一起。因此,您需要做的第一件事是了解您的不同对象是什么以及它们如何相互关联。根据您的描述,您至少提到了两个对象:卡片和版本。
所以我认为这意味着你需要两个表开始,cards
和editions
,但它们是如何关联的?如果存在一对多的关系(即每个版本可以有许多卡片,但每张卡片只属于一个版本),那么您可以在卡片中为版本 ID 设置一个外键。但在这种情况下,您似乎有一个多对多的关系。传统上,这是通过添加第三个表来解释关系来完成的。因此,在这种情况下,您可以添加一个cards_to_editions
表,该表仅包含两列,即卡 ID 和版本 ID。这些都将是它们各自表的外键键,并将形成表的复合主键。
如果有任何特定于关系本身的属性,您还可以将属性添加到cards_to_editions 表中(就像在这种情况下看起来“稀有”一样)。