ソフトウェア プログラミング 公開日 2026.04.27 更新日 2026.04.27

中間テーブルとは?多対多で必要になる理由とピボットテーブルとの違い

中間テーブルとは何かを、多対多の関係でなぜ必要になるのかから整理します。Laravelpivot table との言い方の違い、追加カラムを持たせる場面、設計でよくある失敗まで初心者向けにまとめた記事です。

先に要点

  • 中間テーブルは、多対多の関係 をリレーショナルデータベースで表すための表です。
  • `users` と `roles` のように、片側にも複数、反対側にも複数 ぶら下がる関係では、片方の表に外部キーを1本足すだけでは足りません。
  • Laravel では `pivot table` と呼ばれることが多いですが、一般的には `中間テーブル` `関連テーブル` `relation table` などの言い方もあります。
  • 単なる橋渡しだけでなく、`assigned_at` や `quantity` のような関係そのものの情報を持たせる場面もよくあります。

中間テーブルは、データベース設計を学び始めるとかなり早い段階で出てくる考え方です。
でも最初は、テーブルが1枚増えるのはなぜか 外部キーをどちらかに置くだけではだめなのか が少し分かりにくいです。

特に ORM を使っていると、コード上では belongsToManyManyToManyField のように見えて、裏でどんな表が必要なのかを意識しないまま進むこともあります。
ただ、一覧が重い、重複行が増える、関係に追加情報を持たせたい、といった場面では、結局テーブル設計の理解が効きます。

今回は、中間テーブル多対多を表すための表 として整理しつつ、Laravelpivot table との違い、追加カラムを持たせる場面、よくある設計ミスまでまとめます。

中間テーブルとは

中間テーブルとは、2つの表のあいだに入って、どの行とどの行が結びついているか を記録する表です。
代表例は、ユーザーと権限、記事とタグ、商品と注文の関係です。

たとえば usersroles なら、こんなイメージになります。

  • 1人のユーザーが複数の権限を持てる
  • 1つの権限が複数のユーザーに割り当てられる

このとき usersrole_id を1本置くと、1人のユーザーに1つの権限 しか持てません。
逆に rolesuser_id を置くと、1つの権限が1人のユーザーにしか属せない 形になります。

つまり、両側が複数を持てる 多対多 では、どちらか片方に外部キーを置くだけでは表現しきれません。
そこで user_role のような中間テーブルを作り、user_idrole_id の組み合わせを行として持たせます。

なぜ多対多では中間テーブルが必要になるのか

リレーショナルデータベースでは、1つのセルに 1, 3, 8 のような複数IDを雑に詰め込む設計は扱いにくくなりがちです。
検索、集計、更新、重複防止、整合性チェックが全部つらくなります。

たとえば users.roles = "admin,editor" のように文字列で持ってしまうと、次のような問題が出ます。

  • admin を持つユーザーだけ検索しにくい
  • 権限名の変更で一括置換が必要になる
  • 同じ権限が重複して入っても気づきにくい
  • 外部キー制約を貼れない

中間テーブルを使うと、user_id = 3role_id = 2 のように1行ずつ持てるので、SQLJOIN や集計とも相性がよく、整合性も取りやすくなります。

具体例: users と roles の関係

テーブルを単純化すると、次の3枚になります。

テーブル 主な列 役割
users `id`, `name` ユーザー本体を持つ
roles `id`, `name` 権限の定義を持つ
user_role `user_id`, `role_id` どのユーザーがどの権限を持つかを結ぶ

user_role に次のような行が入っているイメージです。

user_id role_id
1 2
1 3
5 2

これなら、ユーザー1は role 2 と 3 を持つrole 2 はユーザー1と5に付いている が素直に表現できます。

Laravel の pivot table とは何が違うのか

実務では 中間テーブルpivot table がほぼ同じ意味で使われることがあります。
ただし、ニュアンスとしては少し違います。

  • 中間テーブル: データベース設計の一般的な言い方
  • pivot table: とくに Laravel の many-to-many でよく使われる言い方

Laravel の公式ドキュメントでも、many-to-many の関係に対して intermediate tablepivot という表現が出てきます。
つまり Laravel 文脈では pivot table が定着していますが、DB設計全般の話としては 中間テーブル と言っておく方が通じやすいです。

また、Django では many-to-many を ManyToManyField で扱い、追加情報を持たせたいときは through モデルの考え方が出てきます。
Prisma でも implicitexplicit の many-to-many があり、追加メタデータが必要なら relation table を明示モデルとして扱う形が案内されています。

つまりフレームワークごとに呼び方は少し違っても、根っこにあるのは 多対多の関係を1行ずつ持つ表が必要 という同じ考え方です。

中間テーブルに追加カラムを持たせる場面

中間テーブルは IDを2本並べるだけの表 で終わるとは限りません。
実務では、関係そのものに意味がある ので追加カラムを持たせることがよくあります。

たとえばこんな列です。

  • assigned_at いつ割り当てたか
  • assigned_by 誰が割り当てたか
  • quantity 何個ひも付いているか
  • status 有効、保留、無効など
  • sort_order 表示順

たとえば ordersproducts の間なら、中間テーブルに quantityunit_price を持たせたくなります。
ユーザーとチーム の関係なら、owner member のような役割や参加日時を置きたくなることがあります。

この段階になると、単なる橋渡しというより、関係自体が1つのデータ として育ってきます。
Laravel 公式ドキュメントでも、カスタム pivot モデルを使う話があり、追加の振る舞いや属性を持たせる場面が想定されています。

よくある設計ミス

1. 重複行を防ぐ制約がない

user_id = 1, role_id = 2 が何度も入ると、集計や表示が崩れます。
中間テーブルでは、(user_id, role_id) の組み合わせを一意にする設計を考えることが多いです。

2. 片側1対多で十分なのに中間テーブルを作る

1人の社員は1つの部署にだけ所属する のように、実は多対多ではないなら、中間テーブルは不要です。
設計を複雑にする前に、関係が本当に多対多かを確かめた方がよいです。

3. 追加カラムが増えたのに「ただの橋渡し」のまま扱う

status start_at end_at note まで増えてくると、その表はかなり意味を持ち始めます。
アプリ側でも、単なる隠れテーブルではなく、独立したモデルとして扱った方が読みやすくなることがあります。

4. 命名規則だけで分かった気になる

フレームワークが自動で扱ってくれても、裏では JOIN しているだけです。
ORM が便利でも、遅いクエリや重複結果に向き合うときは、テーブル構造と SQL の見え方を理解している方が強いです。

まとめ

中間テーブルは、多対多を表すために2つの表のあいだへ入る表 です。
片方に外部キーを置くだけでは表現しきれない関係を、組み合わせの行 としてきれいに持てるようにします。

覚え方としては、次の3つを押さえるとかなり整理しやすいです。

  1. 片側にも反対側にも複数ぶら下がるなら、多対多を疑う
  2. 多対多なら、中間テーブルで関係を1行ずつ持つ
  3. 関係に意味が増えたら、追加カラムや独立モデルとしての扱いを考える

Laravelpivot tableDjangothrough、Prisma の explicit relation table など、道具ごとの言い方は違っても、考え方の芯はほぼ同じです。
フレームワークの便利機能だけで覚えるより、なぜ1枚増えるのか を先に理解しておくと、後でかなり効きます。

データベース設計の全体像をもう少し広げたいなら ORMとは?何が便利?SQLを知らなくていいわけではない理由を初心者向けに解説 や、アプリ側の代表的なフレームワークLaravelとは?何ができる?向いている開発を初心者向けに解説 もつながります。


参考情報

あとで見返すならここで保存

読み終わったあとに残しておきたい記事は、お気に入りからまとめて辿れます。