【发布时间】: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