アプリに次の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 KEY (`foreign_id`) REFERENCES blogposts (`id`)
-- but only when model='blogpost'
Polymorphic Associationsと呼ばれるデザインを実行しようとしています。つまり、外部キーは、いくつかの関連するテーブルのいずれかの行を参照できます。
ただし、外部キー制約は正確に1つのテーブルを参照する必要があります。 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)
);
各コンテンツタイプは、このスーパーテーブルのサブタイプと見なされます。これは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)
);
BlogPosts
またはUserPictures
に行を挿入する前に、Commentable
に新しい行を挿入して、新しい疑似キーIDを生成する必要があります。次に、コンテンツをそれぞれのサブタイプテーブルに挿入するときに、生成されたIDを使用できます。
これらすべてを実行したら、参照整合性制約に依存できます。