0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SQLアンチパターン解説】ポリモーフィック関連(Polymorphic Associations)

Posted at

はじめに

SQLアンチパターンの中でも、柔軟性を求めた結果、整合性や保守性を犠牲にしてしまう「ポリモーフィック関連(Polymorphic Associations)」について解説します。

ポリモーフィック関連とは?

複数の異なるエンティティ(例:postsphotosなど)に関連付けるために、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と間接的に紐付きます。
  • 柔軟性と整合性のバランスが取れる方法です。

まとめ

項目 ポリモーフィック関連 対応策
柔軟性 高い 中〜高
整合性 低い 高い
クエリの容易さ 難しい 比較的簡単

便利そうに見えるポリモーフィック関連ですが、長期的に見てトラブルの原因になります。
設計段階で「何と何を関連付けたいのか」を明確にして、正規化された設計を心がけましょう!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?