2017-04-01 57 views
0

我正在为一款RPG游戏开发团队建设工具;我使用MySQL作为我的数据库,而InnoDB作为存储引擎。如何在一侧实施有限数量关系的多对多关系? (MySQL)

在游戏中,怪物拥有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约束,否则这在很大程度上解决了这个问题。我可以在我的实际应用程序代码中执行检查,但我非常希望数据库在所有可能的情况下处理数据完整性。

我应该坚持使用我当前的解决方案(怪兽表中的编号插槽),还是有更好的方法在MySQL中实现这一点(通过表结构,触发器等)?

+1

目前的解决方案并不是很好,但你可以很容易地用'where 1234 in(skill1_id,skill2_id,...,skill5_id)来查询'使用'1234'作为skill_id的示例 –

+1

您可以使用触发器来执行最大的slot_num。 – reaanb

回答

0

了解如何在SQL中使用触发器。您需要让DBMS强制执行完整性。总的来说,你总是不能摆脱总是使用不正确的设计和MySQL的SQL子集的声明性约束收集的子集。 (你现在的设计不仅限于有效状态,是吗?)(你实际上没有说出一行是如何映射到一个有序的技能列表的,用于查询,以及一个有序的技能列表如何映射到一行)