我有4种类型的用户,每种都有特定数据,但他们也共享公共数据,例如username
,password
..
我的第一个想法是创建一个带有users
列的主user_type
表。然后,当查询用户数据时,我可以先选择他们的user_type
,然后根据output
运行不同的查询来获取“用户类型”特定数据。
我不喜欢这个,因为我希望我能用一个查询获取所有用户相关数据,理想情况下使用外键。
第二个想法是在user_type
表中没有users
列,而是使用来自特定用户类型表的外键将指向主users
表的行。
我喜欢那样好一点虽然我想我必须运行N个查询,其中N是每次我需要获取用户数据时的用户类型数。
还有其他选择吗?这种情况下的良好做法是什么?
非常感谢
答案 0 :(得分:15)
您的案例看起来像是类/子类的实例。
设计SQL表以处理子类有两种经典方法。每个都有优点和缺点。
一种方法称为“单表继承”。在此设计中,只有一个表适用于所有类型的用户。如果给定列不属于给定行,则交集将保留为NULL。可以添加列以指示用户类型。
另一种方式称为“类表继承”。这很像Nanego给出的答案,只有一些小的改动。用户可以使用一个表,包含所有常用数据和一个id字段。每个子类都有一个表,其中包含与该子类相关的数据。 id字段通常设置为users表中匹配行中的id字段的副本。这样子类密钥可以执行双重任务,既充当主键又充当引用用户表的外键。最后一种技术称为“共享主键”。它需要在插入时进行一些编程,但这非常值得。它强制执行关系的一对一性质,并加速必要的连接。
您可以在SO中查找所有这三种设计作为标签,也可以在网络上查找文章。
single-table-inheritance class-table-inheritance shared-primary-key
答案 1 :(得分:2)
尽管使用磁盘空间效率更高,但拆分成单独表的问题在于您实际需要条件连接 - 根据user_type连接到特定于用户类型的表。代码编写为SQL很痛苦,而现在关心磁盘空间的人呢?
更好的选择是让一个用户表具有足够的列来存储有关任何用户类型的信息,因为他们知道有些列不会用于某些用户类型。使用未使用的列的“低效率”将在执行速度和查询简单性方面得到补偿。
它也很容易扩展,如果你得到另一个用户类型 - 添加列比添加表要容易得多,并且当你添加更多用户类型时,对新列的要求会减少(只是没有关于你需要存储的用户的许多不同的事情)
答案 2 :(得分:0)
我的方法是创建一个包含公共字段的表“Person”,并为每个类型的用户创建一个具有外键“person_id”的表。
在您的请求中,您只需要使用foreign_key连接两个表,以获取一种类型用户的所有数据。
您有多少类型的用户?