はじめに
SQLアンチパターンの中でも、柔軟性を求めた結果、整合性や保守性を犠牲にしてしまう「ポリモーフィック関連(Polymorphic Associations)」について解説します。
ポリモーフィック関連とは?
複数の異なるエンティティ(例:posts
やphotos
など)に関連付けるために、1つのテーブルに対して汎用的な外部キーを持たせる方法です。
一見便利そうに見えますが、実はデータ整合性・クエリの可読性・保守性に大きな問題を抱えています。
❌ アンチパターンの例
CREATE TABLE comments (
id INT PRIMARY KEY,
commentable_id INT,
commentable_type VARCHAR(50), -- 'post', 'photo'など
body TEXT
);
この設計だと、commentable_id
がどのテーブルを参照しているかをcommentable_type
で判断する必要があり、以下の問題が発生します。
問題点
- 外部キー制約を使えない(整合性の保証なし)
- JOINが動的になりSQLが複雑化
- 不正データの混入(存在しないpostやphotoにコメントが付けられる)
解決策①:テーブルを分ける
対象ごとに個別のコメントテーブルを作成します。
CREATE TABLE post_comments (
id INT PRIMARY KEY,
post_id INT,
body TEXT,
FOREIGN KEY(post_id) REFERENCES posts(id)
);
CREATE TABLE photo_comments (
id INT PRIMARY KEY,
photo_id INT,
body TEXT,
FOREIGN KEY(photo_id) REFERENCES photos(id)
);
- 各コメントは明確な対象に結びつき、整合性が保証されます。
- JOINや検索もシンプルになります。
解決策②:共通親テーブルを使う(継承パターン)
全ての対象エンティティに共通の親テーブルを持たせる方法です。
CREATE TABLE entities (
id INT PRIMARY KEY
);
CREATE TABLE posts (
id INT PRIMARY KEY,
title TEXT,
FOREIGN KEY(id) REFERENCES entities(id)
);
CREATE TABLE photos (
id INT PRIMARY KEY,
url TEXT,
FOREIGN KEY(id) REFERENCES entities(id)
);
CREATE TABLE comments (
id INT PRIMARY KEY,
entity_id INT,
body TEXT,
FOREIGN KEY(entity_id) REFERENCES entities(id)
);
- commentsは
entities
を介してpostsやphotosと間接的に紐付きます。 - 柔軟性と整合性のバランスが取れる方法です。
まとめ
項目 | ポリモーフィック関連 | 対応策 |
---|---|---|
柔軟性 | 高い | 中〜高 |
整合性 | 低い | 高い |
クエリの容易さ | 難しい | 比較的簡単 |
便利そうに見えるポリモーフィック関連ですが、長期的に見てトラブルの原因になります。
設計段階で「何と何を関連付けたいのか」を明確にして、正規化された設計を心がけましょう!