あなたがデータベース設計を始めて、最初に頭を抱える瞬間。
それが「多対多」の関係に気づいた時です。
例えば「社員」と「プロジェクト」の関係を想像してください。
一人の社員は、複数のプロジェクトに関わります。
一つのプロジェクトには、複数の社員が参加します。
ここでエクセル脳の持ち主はこう考えます。
「社員テーブルに『参加プロジェクトID』という欄を作って、そこに全部書けばいい」と。
断言します。
それはデジタルな自害です。
1つのマスに「1, 5, 8」とカンマで区切ってデータを詰め込む。
これはデータベースの世界において、最も重い罪の一つ。
あとで「プロジェクトID 5に参加している社員一覧をくれ」と言われた瞬間、あなたのシステムは計算処理でパンクして沈黙します。
検索できない。集計できない。削除も面倒。
この「多対多」という複雑な状況を、スッキリ解決する唯一の道具。
それが中間テーブルです。
仲介役がいれば喧嘩しない
中間テーブルとは、複雑な二者の間に入って関係を取り持つ「仲介人」のことです。
あるいは、2つの素材をくっつける「接着剤」の役割を持つ専用のテーブルです。
社員テーブルとプロジェクトテーブルを直接繋ぐことは正しい設計ではありません。
なので、その間に「社員プロジェクト所属テーブル」という新しいテーブルを置きます。
これが中間テーブルです。
やることは単純。
左側の親分のIDと、右側の親分のIDを、ペアにして記録するだけです。
イメージは「参加名簿」です。
- 社員Aさんが、プロジェクトXに参加する。→ 名簿に「A, X」と書く。
- 社員Aさんが、プロジェクトYにも参加する。→ 名簿の次の行に「A, Y」と書く。
たったこれだけ。
これにより社員テーブルもプロジェクトテーブルも、互いのことを知らずにクリーンな状態を保てます。
余計なデータを持たず、自分の身元情報(名前やメールアドレス)だけを管理していればいい。
関係性はすべて、この「中間テーブル」が引き受けてくれます。
サンプルで見る:関係の記録
論よりコード。
実際にどう保存されるかを見れば一目瞭然です。
まず、ユーザー(users)がいます。
次に、所属するグループ(groups)があります。
ユーザーは複数のグループに入れますし、グループにはたくさんのユーザーがいます。
ここで作る中間テーブルの名前は、一般的にgroup_userやuser_groupsとなります。
中身はこうなります。
// 中間テーブル (user_groups) の中身イメージ
id | user_id | group_id
---+---------+---------
1 | 10 | 99 // ユーザーID:10 は グループID:99 に所属
2 | 10 | 100 // ユーザーID:10 は グループID:100 にも所属
3 | 25 | 99 // ユーザーID:25 も グループID:99 に所属Code language: JavaScript (javascript)
ご覧の通り、ここには具体的な名前やグループ名は入りません。
入っているのは「ID」という背番号だけ。
これで名前が変わっても、IDさえ変わらなければ、この関係性は壊れません。
応用:関係にメモを残す
中間テーブルは、ただIDをつなぐだけではありません。
「その関係がいつ生まれたか」や「その関係の強さ」を記録するのにも使えます。
例えば「ユーザー」が「商品」を買う場合。
中間テーブル(この場合は「注文明細」と呼ばれることが多いです)には、IDだけでなく以下の情報を追加できます。
- 個数(いくつ買ったか)
- 購入時の価格
- 購入日時
もし中間テーブルがなければ、これらの情報は置き場所を失います。
ユーザー側に書くわけにもいかないし、商品側に書くわけにもいきません。
二つが出会ったその瞬間の情報は、二つをつなぐ場所にしか記録できないのです。
シンプルこそ最強
中間テーブルは、一見すると「テーブルが増えて面倒」に見えるかもしれません。
しかし、これがあるおかげでシステムは柔軟になります。
社員が退職しても、中間テーブルの行を消すだけでプロジェクト側のデータは無傷です。
逆にプロジェクトが消滅しても、社員データは無傷。
複雑な絡まり合いを「1対多」という単純な線の集合体に分解する。
これがリレーショナルデータベースの真髄であり、美しい設計の第一歩です。
カンマ区切りで逃げるのはやめましょう。
堂々とテーブルを一つ増やし、綺麗なIDのペアを作ってください。
それが、夜に安心して眠れるエンジニアへの近道です。

コメント