もじれつとがめん

プログラムの忘備録とゲームとかその他色々。

SQLアンチパターン 6章についてメモと感想

6章 ポリモーフィック関連

ポリモーフィック(ポリモーフィズム)

そもそもポリモーフィックとはなにか定義がわからないので調べてみた。 自分の認識としては、
1つの要素が複数の概念に属してもよい状態
を指すと思う。

以下調べた内容の一部

ポリモーフィズム - Wikipedia

ポリモーフィズム(英: Polymorphism)とは、
プログラミング言語の型システムの性質を表すもので、プログラミング言語の各要素(定数、変数、式、オブジェクト、関数、メソッドなど)についてそれらが複数の型に属することを許すという性質を指す。
ポリモルフィズム多態性、多相性、多様性とも呼ばれる。
対義語はモノモーフィズム (Monomorphism)、単態性、単相性で、プログラミング言語の各要素が唯一つの型に属するという性質を指す。

ここの説明が非常にわかりやすかった。
複数のテーブルに対して多対一で紐づくテーブルの設計アプローチ|スパイスファクトリー株式会社

近年ではrails系の記事が非常に多い。
【初心者向け】Railsのポリモーフィック関連付けを理解しよう - Qiita
Railsのポリモーフィック関連とはなんなのか - Qiita

アンチパターンポリモーフィック関連とは

1つのテーブルを複数のテーブルに関連させるような設計の事を指す。
しかし、外部キーが使用できないなどの多くの問題を抱えているので、
あまり良くない手法である。

ただし、Rails等の一部のフレームワークではこの手法で実装が許可されているので、
制御の問題が解消されている為、その場合はフレームワークを使用することでこの設計をある程度は運用することができる。

例えば、
既に存在する、記事(articles)と写真(photos)それぞれにコメント(comments)を新しく付けられるようにしたい場合は、
ポリモーフィック関連を使えば、解決できる。
しかし、このポリモーフィック関連を使った設計では、
外部キーが使用できないので、整合性を保証することができない。

新しく作るコメントテーブル下記のように定義する。

CREATE TABLE comments (
    id PRIMARY KEY,
    parent_type VARCHAR(30), -- 結び付ける親テーブル名が入る articles か photos
    parent_id INT UNSIGNED NOT NULL,
    comment TEXT
);

このように定義すれば、
parent_typeに、対象となるテーブル名を、
parent_idには、対象となるレコードのidをそれぞれ割り当てることで、紐づけが可能となる。

しかし、記事や写真テーブル以外にも別のテーブルがあれば、保存できてしまうし、
外部キーが使用できないので、アプリケーション側で制御するための処理を実装しないとかなりあいまいで不正確なデータになってしまう。

解決策 その1 交差テーブルを使う

例えば先ほどの例を用いると、
既に存在する、記事(articles)と写真(photos)それぞれにコメント(comments)を新しく付けられるようにしたい場合は、
それぞれに新しく交差テーブルを用意する。

記事とコメントを結び付ける articles_comments テーブルと
写真とコメントを結びつける photos_comments テーブルを作成することで、
外部キーを使用しつつ、1つの記事に対して単一か、複数のコメントなのかを制御したりすることが可能になる。

この解決方は比較的簡単な方だけど、
問題としては、記事と写真に対して同じコメントを付けられてしまう問題がある。

解決策 その2 共通の親テーブルを使う

オブジェクト指向みたいに共通の親テーブルを使用する事でも解決できる。
しかし、交差テーブルと同様の問題が発生する。

先ほどの例を再び用いると、
既に存在する、記事(articles)と写真(photos)それぞれにコメント(comments)を新しく付けられるようにしたい場合は、
共通する親テーブルである 投稿(posts)テーブルを作成。
さらに、記事、写真、コメントの親なのでそれぞれに外部キーであるpost_idを追加する。

この設計を利用する場合は、
記事や、写真を新たに作成する場合でも先に投稿テーブルを作成した後で追加する必要がある。

感想

ポリモーフィックについて、きちんと理解しておらずなんとなくの認識なので、
改めて掘り下げることができたので、以前より理解が進んだとは思う。

ところで、読んだ時のメモや調べたことをブログで公開するのは初めてで、
これは著作権的に良いのかな?
読書感想文ならともかく、あまりに本の内容についてそのままを書きすぎるとダメだった気がしてる...
改めて調べてみて、ダメだった場合はすぐに公開を停止します。