MySQL - 条件外键约束

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2002985/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 14:55:21  来源:igfitidea点击:

MySQL - Conditional Foreign Key Constraints

mysqlsqldatabase-designforeign-keyspolymorphic-associations

提问by grzes

I have following commentstable in my app:

comments我的应用程序中有下表:

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?

现在,有没有办法强制对此类数据进行 FOREIGN KEY 约束?

i.e. something like this in comments table:

即评论表中的类似内容:

FOREIGN KEY (`foreign_id`) REFERENCES blogposts (`id`)
-- but only when model='blogpost'

回答by Bill Karwin

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.

您正在尝试进行称为Polymorphic Associations的设计。也就是说,外键可以引用几个相关表中的任何一个中的行。

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 Commentstable. This would violate several rules of relational database design.

但是外键约束必须正好引用一个表。您不能根据表的另一列中的值声明引用不同表的外键Comments。这将违反关系数据库设计的几条规则。

A better solution is to make a sort of "supertable" that is referenced by the comments.

更好的解决方案是制作一种由注释引用的“超级表”。

CREATE TABLE Commentable (
  id SERIAL PRIMARY KEY
);

CREATE TABLE Comments (
  comment_id SERIAL PRIMARY KEY,
  foreign_id INT NOT NULL,
  ...
  FOREIGN KEY (foreign_id) REFERENCES Commentable(id)
);

Each of your content types would be considered a subtype of this supertable. This is analogous to the object-oriented concept of an interface.

您的每个内容类型都将被视为此超级表的子类型。这类似于面向对象的接口概念。

CREATE TABLE BlogPosts (
  blogpost_id INT PRIMARY KEY, -- notice this is not auto-generated
  ...
  FOREIGN KEY (blogpost_id) REFERENCES Commentable(id)
);

CREATE TABLE UserPictures (
  userpicture_id INT PRIMARY KEY, -- notice this is not auto-generated
  ...
  FOREIGN KEY (userpicture_id) REFERENCES Commentable(id)
);

Before you can insert a row into BlogPostsor UserPictures, you must insert a new row to Commentableto generate a new pseudokey id. Then you can use that generated id as you insert the content to the respective subtype table.

在向BlogPostsor插入一行之前UserPictures,您必须插入一个新行Commentable以生成新的伪键 id。然后,您可以在将内容插入到相应的子类型表时使用生成的 id。

Once you do all that, you can rely on referential integrity constraints.

完成所有这些操作后,您就可以依赖参照完整性约束了。