referenceあたりまとめ
外部キーのuser_idカラムを作るときに、二通りの手段がある。
一つはrefference型を使いuser_idを作成する方法。もう片方は自分でuser_idを作成する方法
データベース上で親テーブルuserと子テーブルを結びつける時は
・子テーブルにuser_id(外部キー)を作る
・user_idにindexをつける(付けた方がデータ読み込み時に便利)
・外部制約キーをつける(親テーブルの値しか入らないように・親テーブルのデータが変わると反映)
の3つが必要。
マイグレーション時にreferencesを使うと、(t.references:user)
user_idの作成と、indexの作成を行ってくれる。
しかし、外部制約キー(foreign_key)は作成してくれない。
なので、自分で外部制約キーは自分でつける必要がある。
(初めは外部キーと外部制約キーを混同してごっちゃになった)
マイグレーションについて
index,foreign_key,referenceの理解が曖昧なので、整理する。
まず、マイグレーションファイルはこんな感じ
class CreatePosts < ActiveRecord::Migration[5.2]
def change
create_table :posts do |t|
t.text :body
t.references :user, foreign_key: true
t.timestamps
end
end
end
class AddIndexToテーブル名 < ActiveRecord::Migration
def change
add_index :テーブル名, カラム名
end
end
referencesはデータ型の指示
foreign_keyは列の制約
indexは
そもそものところのマイグレーション
・テーブルが多数(tasks,posts,userとか)
・その中に、カラムが多数(id,title,nameとか)
・そのカラムは属性を持っている
def change
create_table :books do |t|#テーブル作成
t.string :title, limit: 100, null: false#カラム作成
#(まずフィールド定義t.string)(その後フィールド名定義 :title)(その後列制約)
end
end
t.stringとかはデータ型の指定(フィールドの定義)
(利用できるデータ型は他にtext, date, boolean, integer, textなど多数)
特殊なフィールド定義をするためのメソッドとしてtimestampsや、referencesなどがある。
t.timestamps メソッド
→日付時刻型のcreated_atとupdated_at列を生成する
t.references
→外部キー列を生成する
ex) t.references:bookとした場合は booksテーブルの外部キーとして、book_idを生成する
今回はcreate_tableメソッドを用いているが、他にも色々メソッドがある
add_column,add_index,add_foreign_key,change_table,executeなど
foreign_key,index,referenceの意味
indexとは?つけるとどんなメリットがあるのか?
「この列だけ検索したい」「この列を基準に並べ替えしたい」というときに使える
メリット:データベースの読み込み速度が改善可能(貼り方やデータ数にもよる)
テーブルの中の特定のカラムのデータを複製し検索が行いやすいようにしたもの。
データベースにインデックスをつけることができる。
インデックスがあれば全部のデータを調べずに、高速に検索を行える。
ex)膨大なデータの中から、aaa@mail.comというデータを調べたいとする。
この場合、インデックスがなければ、全てのデータからこのデータを探らなければいけないため、非効率。
インデックスがあれば、emailのインデックス部分から探すだけで良い。
indexの貼り方
class AddIndexToテーブル名 < ActiveRecord::Migration
def change
add_index :テーブル名, カラム名
end
end
「ある程度多くのデータを格納するテーブルの、格納される値がそれぞれ異なるようなカラムの中で、検索がよく行われるカラム」にindexを貼ると良いらしい
参考:データベースにindexを張る方法https://qiita.com/seiya1121/items/fb074d727c6f40a55f22
foreign_keyとは?外部制約キーをつけるとどんなメリットがあるの?
親テーブルと子テーブルの間で、整合性をとるためのキー
データを参照する側(子テーブル側)に外部制約キーを設置する。
子テーブルに設置した外部制約キーには何でも入れられるわけではなく、
親テーブルに入っている値しか入れられなくなる。(user_idに何にでも入れれる訳ではなく、実際にあるuser_idしか入れれなくなる)
親テーブルのuser_idを変更、削除すると、子テーブルにあるforeign_keyも変更、削除される。
外部キーの作成
create_tableで
t.references :bookを使うと、book_idとが作成される
add_foreign_keyメソッド
add_foreign_key :作成先のテーブル名, :参照先のテーブル名
add_foreign_key :reviews, :books
→reviewsテーブルに、booksテーブルを参照する外部キーを設置する
待て待て、外部キー列と外部キー制約があるんか
テーブルを作るときに、t.reference、カラムを追加するときにadd_referenceすれば、外部キーのカラムを作成することができる。
参考:https://teratail.com/questions/63406
https://www.dbonline.jp/
referenceとは?使うとどんないいことがあるの?
references型を使うことで、自動で、〇〇_idという外部キーを設定してくれるのが良いところ
外部キーを作成するときの一つの手法(普通にuser_idカラムを設定することもできる)
t.references :bookとかで、外部キーを作成する
外部キーをreferences型カラムで保存する
https://qiita.com/sinagaki58/items/7edea51ef00e393834ca
Railsの外部キー制約とreference型について
https://qiita.com/ryouzi/items/2682e7e8a86fd2b1ae47
外部キーuser_idをつくるだけじゃダメなの?
なぜ外部キー制約と、インデックスを付けなければいけないのか
→外部キー制約(foreign_key: true)があると、子テーブルにあるuser_idが親テーブルの値しか入らなくなるから。しかも親テーブルの値が変わると、子テーブルの値も変わるので使う。
どこにindex付けてんの
→user_idに作られる