[多対多] 中間テーブルとはなんぞや

関係データベースで出てくる、中間テーブルとはなんぞや。

ざっくりというならば、多対多をデータベースで表現するために必要なのが中間テーブルです。

(一対一とか一対多も良くわからんのに多対多かよ。とか思った人もこの後の例見ればちょっとは分かるかも?)

以前のデータベースの正規化の記事でも述べましたが、現実の関係性を2次元のテーブルに落とすためには、そのままじゃ無理なんですよね。

必ず行と列ので表現する必要があり、一つの項目に複数項目を入れることは原則できません。(配列カラムとかJSONカラムとかあるらしいけど原則使わない)

なので、中間テーブルという物が必要になるんです。

例えば、男性と女性がいます。
それぞれ、男性テーブルと女性テーブルにいくつかデータが入っています。

男性テーブル

id name
M1 太郎
M2 佐助
M3 与作

女性テーブル

id name
F1 花子
F2
F3 薫子

このテーブルに、男性と女性は付き合う可能性があるという仕様をいれます。男性に一人彼女を持つことができるので、男性テーブルに女性のidをもたすことで、1対1の関係になります。
下のテーブルから、太郎が菊と、佐助が花子と付き合っているという関係性が見えます。

男性テーブル

id name girl_id
M1 太郎 F2
M2 佐助 F1
M3 与作

女性テーブル

id name
F1 花子
F2
F3 薫子

しかし、男性は浮気する生き物。 2又、3又と、複数の女性と同時に付き合う可能性があるという仕様になりました。

それを表現するには、男性テーブルのカラムに複数の女性のidを入れる必要がでてきます。が、先ほども記述してますが、カラムに複数項目入れることは原則無理なので、逆に女性のテーブルに彼氏idを持たせることで、誰が誰と付き合ってるかがわかるようにしました。

これが、1対多の関係です。

下のテーブルからみると、太郎は菊の他に実は薫子とも付き合っていることがわかります。

男性テーブル

id name
M1 太郎
M2 佐助
M3 与作

女性テーブル

id name boy_id
F1 花子 M2
F2 M1
F3 薫子 M1

しかし、世の中の女性もそんなにいい子ばかりじゃないです。
男は浮気する生き物とかいいながら平気で女も浮気する。という仕様が盛り込まれることなりました。

さて、男のほうの彼女カラムに複数入り、女のほうの彼氏カラムも複数で・・・。もうこうなると手の打ちようがありません。

このように、あるテーブルのレコードがお互いに相手のレコードと複数の関係を持てるようになった場合の関係性を多対多といいます。

さて、このままでは、2次元のデータベースでは再現できません。

そこで、お互いの間に中間テーブルを作ります。

下のテーブルから分かることは、太郎は、菊と薫子と付き合って、佐助は、花子と薫子とも付き合うことになって、女は浮気しないと思ってたのに、薫子は二人同時に付き合うことになったのが表現されています。

男性テーブル

id name
M1 太郎
M2 佐助
M3 与作

男女関連テーブル

boy_id girl_id
M1 F2
M1 F3
M2 F1
M2 F2

女性テーブル

id name
F1 花子
F2
F3 薫子

要するに、2次元である関係データベースでは、1対1や1対多(多対1)は、表現できても、多対多は表現できない。そこで、中間テーブルをあえて作ることで、多対多を1対多と多対1と関係性を分解するということになります。

このため中間テーブルを関連テーブルとよんだりもする。

プログラムの場合、配列の配列で2次元を表現でき、さらに配列の配列の中にさらに配列をもつことで、多次元配列を作ることができ、XMLやJSONでも表現できます。
しかし、関係データベースでは、原則できません。
それが、デメリットでもありメリットでもあります。

以上、与作に幸あれ!

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">