关于sql:MySQL – 条件外键约束

MySQL - Conditional Foreign Key Constraints

我的应用程序中有以下"评论"表:

1
2
3
4
5
6
7
comments
--------
id           INT
foreign_id   INT
model        TEXT
comment_text TEXT
...

此表的目的是存储应用程序各个部分的评论-它可以存储博客文章的评论,即:

1
1|34|blogpost|lorem ipsum...

用户图片:

1
2|12|picture|lorem ipsum...

等等。

现在,有没有一种方法可以强制对这些数据使用外键约束?

例如,评论表中的类似内容:

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


你试图做一个叫做多态关联的设计。也就是说,外键可以引用几个相关表中的任何一个表中的行。

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

更好的解决方案是生成一种"超级表",由注释引用。

1
2
3
4
5
6
7
8
9
10
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)
);

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

1
2
3
4
5
6
7
8
9
10
11
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)
);

在将行插入到BlogPostsUserPictures之前,必须将新行插入到Commentable以生成新的伪键ID。然后,可以使用生成的ID将内容插入到相应的子类型表中。

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