データベースについて（リレーション、正規化、テーブル設計）

# データベース入門

## データベースとは

サイトの顧客情報や商品情報などの**データを管理する場所**

## DBの種類

RDB

- **MySQL**

    無料で使えて、実際の仕事現場でもよく使われている

- PostgreSQL
- Oracle

どれを使っても基本的な役割は一緒

## テーブル/カラム／レコード

- テーブル

    エクセルで言うところの**シート**

    データの種類でテーブルごとに管理をする

- カラム

    エクセルで言うところの**列**

- レコード

    エクセルで言うところの**行**

## SQLとは

データベースはコマンドで操作する

このデータベースを操作する**コマンド（言語）をSQL**という

追加、変更、削除など

例：select * from users limit 2 ;

usersのテーブルから2件のデータを表示する

[参考動画【データベース入門】](https://www.youtube.com/watch?v=IiX6J0FfGng)

# DBの設計＃１

## DBのリレーション

- １：ｎ（１：多）

    会社情報　：　社員情報

    一つの会社に複数の社員が入ることができる

- ｎ：ｎ（多：多）

    社員情報　：　サークル

    社員一人につき複数のサークルに所属できる

    サークルは複数の社員をかかえることができる

- １：１

    社員情報　：　個人情報

    社員一人につき一つの個人情報

## ER図

### IE記法

　**テーブル同士のリレーション（関係）を表現する**

【○】・・・０

【｜】・・・１

【鳥の足】・・・ｎ

リレーション関係で**親と子の関係**がある場合**角を丸く**表現する

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/c603cff4-a838-70ff-0296-2ad9dc42d0ac.png)

### 中間テーブル

- ｎ：ｎのリレーション設計する場合に中間に置くテーブル
- 中間テーブルには余計なカラムを持たせない
- リレーションの橋渡し役

### SQLアンチパターン

やってはいけない設計パターンを解説した書籍

【Amazon】[https://www.amazon.co.jp/gp/product/4](https://www.amazon.co.jp/gp/product/4)...

### ツール

- Cacoo
- MySQL Workbench

[参考サイト](https://it-koala.com/entity-relationship-diagram-1897)

[参考動画#1【リレーションER図】](https://www.youtube.com/watch?v=T6g-DLWHscw)

# DBの設計#2

## 正規化

### データの繰り返しをなくして整理すること

手順は2つ

- 横方向の繰り返しをなくす
- 縦方向の繰り返しをなくす

例：青いカラムのデータが**横方向に重複しているデータ**

![正規化１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/4a316936-58ab-3e13-23cc-607f541508e3.png)


このデータを縦方向に伸びるよう並べ替えて**横方向の繰り返しをなくす**

![正規化２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/55de37e3-cf84-2b93-67d0-168c816edd0b.png)


項目がグレーのカラムは**縦に繰り返し**が発生している

この縦方向の繰り返しをなくすために、青いカラムのデータを別テーブルに切り出す

![正規化３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/279f6a60-640e-ac89-a34f-c1d3d9c975a8.png)


注文番号に紐付けて管理するようにテーブルを分けている

上記のように縦方向の繰り返しをなくすには**１：ｎの関係のテーブルに切り出す**

その他の縦の繰り返しをそれぞれ切り出す

![正規化４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/f60b55da-3ffb-4dc2-54e6-932eaf7e5468.png)

![正規化５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/e5fe2867-701f-c399-23b4-79779519cbdd.png)


[参考サイト](https://proengineer.internous.co.jp/content/columnfeature/6480)

[参考動画#2【正規化](https://www.youtube.com/watch?v=WEmY9s0Ky88)】

# DBの設計#3

## テーブル設計の手順

1. **システム要件を把握**
    1. システムの要件と機能を明確にすること

        要件例：AmazonのようなECサイト

        機能例

        - フロント画面
            - 商品検索
            - 商品詳細ページ
            - マイページ
        - 管理者画面
            - ログイン
            - 商品管理
            - 商品カテゴリー一覧
2. **テーブルの概要設計（ラフスケッチ）**
    1. テーブルの一覧と主要なカラムを書き出す
    2. 闇雲に出さず,機能一覧をみながらシナリオを思い浮かべながら洗い出す

        テーブル例

        - 店舗テーブル
            - 店舗名
            - メールアドレス
            - パスワード
        - 商品カテゴリーテーブル
            - カテゴリ名
        - 商品テーブル
            - 商品名
            - 価格
            - 在庫
        - ユーザーテーブル
            - 名前
            - 住所
            - メールアドレス
        - 購入履歴テーブル
            - 購入日
            - 合計金額
3. **テーブルの詳細設計（最終調整）**
    1. 日本語（論理名）を英語名（物理名）に変換（**命名規則参照**）
    2. カラムに型を付ける
        1. **varchar**という型を使う場合、桁数が２の累乗数となる

            例：2,4,8,16,32,64,128,256,512...

            **※256は255にする**（256以上だとインデクスが貼れないから）

        2. 全てのテーブルに（　**id,　created_at,　updated_at**　）というカラムを3点セットで追加する

            **id**

            - **プライマリーキー**
            - int型　AutoIncrement
            - shop_idのような名前にしない

            **created_at  /  uptated_at**

            - datetime型
            - _date*ではなく*_atと命名
        3. ER図を書きながら正規化
            1. 1：ｎの関係のｎ側に**外部キー**を追加

                例：shops  |—————○Items

                この場合Itemsテーブルに**shop_id**カラムを追加

                **外部キー命名規則**：相手テーブル名の（**単数形_id**）

            2. ER図を書きながら**正規化**していく

                例：購入履歴テーブル|——○**購入履歴明細テーブル**|———|商　品テーブル（正規化で購入履歴テーブルから切り出す）

            3. ｎ：ｎの関係のテーブルの間に中間テーブルを持たせる

                この場合**外部キーは中間テーブルに持たせる**

        4. インデクスや制約条件をつける

            **インデクス（検索を早くするためのもの）**

            - 検索のキーになるカラムに付ける
            - プライマリーキーや外部キーにはつけない→自動でつく

            **制約**

            - 全てのカラムに可能な限りつける

### 命名規則

- 半角アルファベット、半角数字、アンダーバー
- テーブル名は複数形、カラム名は単数形
- text1,text2のような雑な名前にしない

### 予約後

- If
- Null
- Limit
- Date　など

予約後はテーブル名やカラム名には使わない

このほかたくさんあるので、一覧を見ておくとよい

### 制約

- NOT NULL制約

    入力必須になる場合の制約

- ユニークキー制約

    値の重複を防ぐ制約

- 外部キー制約

    リレーション先にレコードがあることを保証する制約

[参考動画＃３](https://www.youtube.com/watch?v=D5UgoChhrSo)![正規化５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/fb9b12ac-aca4-4b3a-cdbd-f132ad7e77b5.png)
![正規化５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/8e6bf3df-ac20-a4dc-477c-9005a44474a1.png)