4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

中間テーブルと多対多のアソシエーションについてまとめてみた

Posted at

DBのレッスンで習った「DB設計」の復習です。
多対多の関係のテーブルをどうやって表すのかが難しかったので、備忘録してまとめてみます。

まずは一対多のテーブルの作り方から

「生徒」と「部活」のテーブルを例にして考えます。
生徒は必ず1つだけ部活を選んで所属するという前提条件があったとしたら、部活は複数人の部員を抱えていることになるので、一対多の関係が成り立ちます。
どの生徒がどの部活に所属しているか分かるようにしたい場合、部活のidを生徒に紐づければ良いので、テーブルは以下のようになります。

studentsテーブル

|Column|Type|Options|
|------|----|-------|
|student|string|null: false, index: true|
|club_id|integer|null: false|

Association
belongs_to :club
clubsテーブル

|Column|Type|Options|
|------|----|-------|
|club|string|null: false, index: true|

Association
has_many :students

これらをもとにデータを入れるとこんな感じになります。
studentsテーブル

id student club_id
1 田中 太郎 3
2 山田 花子 1
3 高橋 順子 1

clubsテーブル

id club
1 バスケ部
2 野球部
3 ハンドボール部

この二つのテーブルから、田中太郎さんはハンドボール部に所属していて、山田さんと高橋さんはバスケ部に所属しているというデータをとることができます。

多対多の関係のテーブルの定義の方法

ではもし前提条件が生徒は複数の部活に所属しても良いとなったらどうなるでしょう。
上の生徒のテーブルにカラムを足して以下のようにしたとします。

studentsテーブル

id student club1 club2
1 田中 太郎 3 2
2 山田 花子 1
3 高橋 順子 1 3
これは良くない例です。なぜなら、このように所属しているクラブを重複して書く書き方は、データベースの設計として間違ってるためです。そこで、中間テーブルを用意する必要があります。
中間テーブルとは、多対多の関係を表すために用意するテーブルです。
今回の場合、どの生徒とどの部活が結びつくかを表すテーブルをもう一つ用意すればいいので、そのテーブルをrelationsと名付けます。

studentsテーブル

id student
1 田中 太郎
2 山田 花子
3 高橋 順子

clubsテーブル

id club
1 バスケ部
2 野球部
3 ハンドボール部

relationsテーブル

id student club
1 1 3
2 1 2
3 2 1
4 3 1
5 3 3

こうすることで、studentカラムやclubカラムを重複することなく、関係を表すことができます。
定義の方法は以下のようになります。

studentsテーブル

|Column|Type|Options|
|------|----|-------|
|student|string|null: false, index: true|

Association
has_many :relations
has_many :clubs, through: :relations
clubsテーブル

|Column|Type|Options|
|------|----|-------|
|club|string|null: false, index: true|

Association
has_many :relations
has_many :students, through: :relations

二つのテーブルのAssociationに注目するとさっきまでの定義になかったthrough: :relationsが見られます。これは、中間テーブルを明確に表すために必要な定義です。
また、中間テーブルはthroughの前に定義する必要があります。 これはプログラミングが上から順番に読まれる性質があるためです。

relationsテーブル

|Column|Type|Options|
|------|----|-------|
|student|references|null: false, foreign_key: true|
|club|references|null: false, foreign_key: true|

### Association
belongs_to :student<br>
belongs_to :club<br>

relationsテーブルでは、指定するカラム名をstudent_idとせずにstudentとし、型はinteger型ではなくreference型にします。これはinteger型だと外部キー制約にならないためです。
Associationはひとつずつの組み合わせを表すためbelongs_toでそれぞれのテーブルを指定します。

まとめ

1.中間テーブルとは多対多の関係の2つのテーブルをつなぐためのテーブル
2.中間テーブルでない2つのテーブルでは、Associationで
thorough: :中間テーブル と記述する必要がある
3.中間テーブルでは、カラム名に_idは省き、型はreference型を指定する。

参考ページ

railsガイド
railsで多対多のアソシエーションの作り方と、出来ること
Railsの外部キー制約とreference型について

4
5
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
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?