我们有三种不同的类型(用户,文章,评论),用户可以订阅。 每种类型都有一个单独的表。我希望用户能够订阅其他用户,文章或评论。
订阅表列:
id(integer, AI)
type('String, can be 'article', 'comment', 'user')
ref('integer', indicates the index key to an external table)
user_id('integer', foreign key to the users table)
因此,此行将是id = 101的用户,该用户订阅ID为99的评论
1 | comment | 99 | 101
id = 101的用户也订阅了id = 88的文章
1 | article | 88 | 101
你明白了。这是一个很好的设计吗?
答案 0 :(得分:0)
由于'魔术字符串'元素,我会避免这种方法。您的查询必须依赖于读取字符串来决定用户是否订阅了某些内容。
我会考虑采用不同的方法并拥有一个只代表用户的表,然后使用“链接”表来匹配用户(通过他们的ID)与特定类型的提示。
例如:
Users UsersInArticles Articles
----------- ---------------- ----------
UserID UserID ArticleID
Name ArticleID Title
Address Body
etc... etc..
UsersInArticles 表表示订阅特定文章的用户(按UserID)(按条款ID)。
此方法允许您使用外键关系维护关系完整性(例如,您可以确保用户无法订阅数据库中不存在的文章。)
此外,没有涉及魔术字符串。
使用这种方法,要查找订阅文章的所有用户(例如文章123),您只需执行以下查询(而不是与字符串列进行比较以查找“文章”等)。
SELECT UserID from UsersInArticles WHERE ArticleID = 123
我还怀疑这个shema允许比代表订阅类型的varchar列更快的查询。
答案 1 :(得分:0)
这是一个好的设计吗?
没有
DBMS无法为您强制执行引用完整性(通过外键)。在并发环境中,手动实现参照完整性非常难以正确执行(没有竞争条件)和且性能良好。
相反,您可以使用多个订阅表(每种类型的“可订阅”项目一个)。或者,如果您希望避免表扩散,请使用多个FK或继承,类似于this(但您不一定需要强制执行FK排他性)。