MySQL - 条件外键约束
我的应用程序中有以下 comments
表:
comments
--------
id INT
foreign_id INT
model TEXT
comment_text TEXT
...
该表的想法是存储我的应用程序各个部分的评论 - 它可以存储博客文章的评论,即:
1|34|blogpost|lorem ipsum...
用户图片:
2|12|picture|lorem ipsum...
等等。
现在,有没有办法对此类数据强制外键约束?
即评论表中类似这样的内容:
FOREIGN KEY (`foreign_id`) REFERENCES blogposts (`id`)
-- but only when model='blogpost'
I have following comments
table in my app:
comments
--------
id INT
foreign_id INT
model TEXT
comment_text TEXT
...
the idea of this table is to store comments for various parts of my app - it can store comments for blog post i.e.:
1|34|blogpost|lorem ipsum...
user picture:
2|12|picture|lorem ipsum...
and so on.
now, is there a way to force FOREIGN KEY constraint on such data?
i.e. something like this in comments table:
FOREIGN KEY (`foreign_id`) REFERENCES blogposts (`id`)
-- but only when model='blogpost'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您正在尝试进行一种称为“多态关联”的设计。也就是说,外键可以引用多个相关表中任何一个中的行。
但外键约束必须精确引用一个表。您无法根据
Comments
表的另一列中的值来声明引用不同表的外键。这将违反关系数据库设计的几条规则。更好的解决方案是制作一种由评论引用的“超级表”。
您的每种内容类型都将被视为此超级表的子类型。这类似于接口的面向对象概念。
在将行插入
BlogPosts
或UserPictures
之前,您必须将新行插入Commentable
以生成新的伪键 ID。然后,您可以在将内容插入到相应的子类型表时使用生成的 ID。一旦完成所有这些,您就可以依赖引用完整性约束。
You're attempting to do a design that is called Polymorphic Associations. That is, the foreign key may reference rows in any of several related tables.
But a foreign key constraint must reference exactly one table. You can't declare a foreign key that references different tables depending on the value in another column of your
Comments
table. This would violate several rules of relational database design.A better solution is to make a sort of "supertable" that is referenced by the comments.
Each of your content types would be considered a subtype of this supertable. This is analogous to the object-oriented concept of an interface.
Before you can insert a row into
BlogPosts
orUserPictures
, you must insert a new row toCommentable
to generate a new pseudokey id. Then you can use that generated id as you insert the content to the respective subtype table.Once you do all that, you can rely on referential integrity constraints.
在 MySQL 5.7 中,您可以拥有一个多态表并享受诸如多态外键之类的功能!
需要注意的是,从技术上讲,您需要将其实现为多个列上的多个 FK(每个有注释的实体一个),但实现可以仅限于数据库端(即,您不需要担心您的数据库中的这些列)。代码)。
这个想法是使用MySQL的生成列:
您可以忽略
generated_* 列;当添加或修改注释时,MySQL 将自动填充它们,为它们定义的 FK 将确保数据的一致性。
显然,它会影响大小要求和性能,但对于某些(大多数?)系统来说,它可以忽略不计,并且通过更简单的设计实现数据一致性所付出的代价是值得的。
In MySQL 5.7 you can have a single polymorphic table AND enjoy something like a polymorphic foreign key!
The caveat is that technically you will need to implement it as multiple FKs on multiple columns (one per each entity that has comments), but the implementation can be limited to the DB side (i.e. you will not need to worry about these columns in your code).
The idea is to use MySQL's Generated Columns:
You can ignore the
generated_*
columns; they will be populated automatically by MySQL as comments are added or modified, and the FKs defined for them will ensure data consistency as expected.Obviously it would impact both the size requirements and performance, but for some (most?) systems it would be negligible, and a price worth paying for achieving data consistency with a simpler design.