【问题标题】:How to implement a many-to-many relationship with a limited number of relations on one side? (MySQL)如何在一侧实现具有有限数量关系的多对多关系? (MySQL)
【发布时间】:2017-04-01 18:50:00
【问题描述】:

我正在为我玩的 RPG 开发团队建设工具;我的数据库使用 MySQL,存储引擎使用 InnoDB。

在游戏中,怪物有 5 个技能槽位,您可以通过物品添加它们,它们的排列顺序很重要(如果添加了没有可用槽位的新技能,最旧的技能将被覆盖) - 目前,我有这样的monsters 表设置:

monster_id int not null,
species_id int not null,
user_id int not null,
skill1_id int, # (fkey to skills.skill_id)
skill2_id int, # (fkey to skills.skill_id)
skill3_id int, # (fkey to skills.skill_id)
skill4_id int, # (fkey to skills.skill_id)
skill5_id int, # (fkey to skills.skill_id)
# other irrelevant columns...

这使技能保持有序,并防止怪物拥有的技能超过允许的最大值。然而,这似乎不是一个很好的解决方案——这个设置不允许我快速查询“选择所有在任何插槽中具有 X 技能的怪物”。我可以查询所有 5 个插槽,但这似乎效率很低,因为它会依赖于一堆链式连接(它也不会与我正在使用的 ORM 配合得很好,尽管我可以放下来编写自己的查询真正需要的地方)。

如果我像这样使用联结表 monsters_skills 标准化这种关系:

monster_id int not null,
skill_id int not null,
slot_num int not null,
primary key (monster_id, slot_num) # enforce one skill per-slot

这将使查询“在任何插槽中具有 X 技能的所有怪物”变得更加容易......但数据库不会强制每个怪物的最大技能数量 - 据我所知,MySQL 没有正确支持 CHECK 约束,否则这将在很大程度上解决问题。我可以在我的实际应用代码中进行检查,但我更喜欢在所有可能的情况下处理数据完整性的数据库。

我应该坚持我目前的解决方案(monsters 表中的编号槽),还是有更好的方法在 MySQL 中实现(通过表结构、触发器等)?

【问题讨论】:

  • 当前的解决方案不是很好,但您可以使用where 1234 in (skill1_id, skill2_id, ..., skill5_id) 使用1234 作为skill_id 的示例轻松查询
  • 您可以使用触发器来强制执行最大 slot_num。

标签: mysql sql database foreign-keys database-normalization


【解决方案1】:

了解如何在 SQL 中使用触发器。您需要让 DBMS 强制执行完整性。通常,您将无法摆脱总是使用不正当的设计和 MySQL 的 SQL 的声明性约束的可怜集合的子集。 (无论如何,您当前的设计不仅限于有效状态,是吗?)(您实际上并没有说明行如何映射到技能的有序列表以进行查询,以及技能的有序列表如何映射到行,用于更新。但您似乎依赖于用户/程序的正确更新。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    • 2015-02-06
    • 1970-01-01
    • 2023-02-08
    • 2012-09-29
    • 2019-09-12
    相关资源
    最近更新 更多