自分用メモ(マイグレーション,index,foreign_key,reference)

##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の理解が曖昧なので、整理する。

まず、マイグレーションファイルはこんな感じ

```ruby
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
```
```ruby
class AddIndexToテーブル名 < ActiveRecord::Migration
  def change
    add_index :テーブル名, カラム名
  end
end
```

referencesはデータ型の指示
foreign_keyは列の制約
indexは

##そもそものところのマイグレーション
・テーブルが多数(tasks,posts,userとか)
・その中に、カラムが多数(id,title,nameとか)
・そのカラムは属性を持っている

```ruby
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の貼り方

```ruby
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/](https://www.dbonline.jp/mysql/table/index11.html#targetText=FOREIGN%20KEY%E5%88%B6%E7%B4%84(%E5%A4%96%E9%83%A8%E3%82%AD%E3%83%BC%E5%88%B6%E7%B4%84)%E3%81%A8%E3%81%AF%E8%A6%AA%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB,%E8%A8%AD%E5%AE%9A%E3%81%95%E3%82%8C%E3%82%8B%E5%88%B6%E7%B4%84%E3%81%A7%E3%81%99%E3%80%82&targetText=%E5%8F%82%E7%85%A7%E3%81%99%E3%82%8B%E5%81%B4%E3%81%AE%E5%AD%90,%E5%88%B6%E7%B4%84%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

##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に作られる