43テーブルのDB設計をしてみて思った、DB設計する上で認識しておくべきこと。ちゃんと設計することで、シンプルなSQLクエリだけで開発できるようになる。

覚えておいたほうがいいこと

  • テーブル名は複数形にする
  • IDをidにしない
  • NOT NULL制約
  • UNIQUE制約
  • 外部キー制約
  • テーブルをちゃんと分ける
  • UUID / ULID
  • カラムを無駄に増やさない
  • 予備カラムを設定しない

テーブル名は複数形にする

以下のようにusersdepartmentsなど複数形にして名前を決定する。

CREATE TABLE users (
    username VARCHAR(50) NOT NULL
    password CHAR(36) NOT NULL
    department_id CHAR(36) NOT NULL
    solt CHAR(36) NOT NULL
    PRIMARY KEY (username)
    FOREIGN KEY (department_id) REFERENCES departments (department_id)
)
CREATE TABLE departments (
    department_id CHAR(36) NOT NULL
    department_name VARCHAR(50) NOT NULL
    PRIMARY KEY (department_id)
)

IDをidにしない

IDのカラム名をidにしない。user_idrole_idなど。○○_idにする。

例外として、独自にコーディング規約がidとして付けると記載があるならコーディング規約に従う。

NOT NULL制約

なるべくNULL値を入れない。

UNIQUE制約

重複バグがおきない。DISTINCTが必要ない。データ追加(INSERT)時ラク。
WHERE句での条件一致で役に立つ。無駄なSQLを発行しなくてよい。

INSERT INTO calender (date) VALUES ('2022-12-25');

個人的にはUNIQUE制約が一番好き。

外部キー制約

複数の箇所にデータ(文字列など)を保存しない。idを付けて外部キーを設定する。

テーブルをちゃんと分ける

テーブル構造(カラム)が同じになっていてもテーブルを分ける。

UUID / ULID

UUID、ULIDを使う。むやみにAUTO INCREMENTしない。

カラムを無駄に増やさない

わざわざ年月日を分けているテーブル。意味ない。

CREATE TABLE calender (
    date DATE NOT NULL UNIQUE -- 日付
    year VARCHAR(4) NOT NULL -- 年
    month VARCHAR(2) NOT NULL -- 月
    day VARCHAR(2) NOT NULL -- 日
    PRIMARY KEY (date)
)
SELECT concat(year, '/', month, '/', day) FROM calender;
-- 結果: 2022/12/25

これだけ。クエリで対応すべき。

CREATE TABLE calender (
    date DATE NOT NULL UNIQUE -- 日付
    PRIMARY KEY (date)
)
SELECT DATE_FORMAT(date, %Y/%m/%d) FROM calender;
-- 結果: 2022/12/25

予備カラムを設定しない

いつ使うかも分からない予備のカラムを設定しない。その都度ALTERを使って対応すること。

/*
データ型、制約も不明な予備1、予備2。とりあえずVARCHAR(255)設定
運用後、予備1が数値だけのデータだったらVARCHARで運用?
*/
CREATE TABLE calender (
    date DATE NOT NULL UNIQUE -- 日付
    reserve1 VARCHAR(255) -- 予備1
    reserve2 VARCHAR(255) -- 予備2
    PRIMARY KEY (date)
)

予備を設定している時点で設計がちゃんとできていない証拠。だいたい文字列型で設定しがち。不安だからで設定してはいけない。無駄は省こう。

予備が本当にほしいなら、どんな用途で使用するか?など、ちゃんと要件を確定して具体的なカラム名と型を決めること。