⚙️

難しいことは置いといて、データベースを設計する

2023/11/03に公開

この記事の目的

データベースの設計段階には、論理設計物理設計エンティティ正規化...などなど小難しい用語がたくさんあり、初心者が嫌になるポイントがたくさんあります。

最初から完璧な設計をしようと思って、上記のようなことから勉強しなきゃ!って思っちゃうと、なかなか前に進めず、データベースを嫌いになってしまいます。(自分もそうでした)

ということで、こういった部分を難しく考えずに、「とりあえずデータベースを作る!」ということを目標にします。

そして書いていく中で、「ここってこうした方が後々便利なのでは?」みたいにその都度修正しながら、結果として、「小難しいことをクリアしているデータベースが出来上がっちゃった」という状態を目指します。

サービスの内容

本記事では、一般的な「ECサイト」を例にデータベース設計を行います。

手順①:まずは表を作る

データベースなんてただの表です。
データベース設計は表を作るところから始まります。

そのためにまずはサービス内で必要そうな情報をすべて書き出していきます。

ECサイトであれば、必要そうな項目はこんな感じ。

  • 注文した時間
  • 注文した人
  • 住所
  • 注文した商品の商品名、個数、単価
  • 注文の合計金額

まずはこれらをすべて一つの表に書き出していきます。
表1

手順②:横方向の繰り返しをなくす

上記の表でデータベースを作るならもう終わりなのですが、
いろいろと問題があります。

まず、青色で囲っている部分を見てください。
表2

ここは同じ内容が横方向に連続しています。
同じユーザーが同時に複数の商品を購入すれば、この表はどんどん横に拡張していくことになります。

データベースの前提として、横方向にデータを追加していくことはしません。
データは下に伸ばしていく(行を追加していく)ように設計するべきです。

以下のように表を変更すれば、横方向への繰り返しはなくすことができます。

表3

手順③:縦方向の繰り返しをなくす

横方向の繰り返しをなくすことができましたが、まだ不完全です。

例えばユーザーAが名前や住所を変更した場合、この表の中から購入者がユーザーAであるデータをすべて修正しなければならなくなります。

ではどうすればこの問題を解決できるかと言いますと、テーブルを分けてしまえばいいですね。

表4

もとのテーブルから、「購入者」と「住所」を分離し、「ユーザーID」というカラムを追加しました。

このユーザーIDは、分離したユーザーテーブルのユーザーIDと紐づいているため、例えば、注文テーブルから注文番号1の購入者は誰か知ろうと思ったら、注文番号1のユーザーIDは「Y0001」ということは注文テーブルから分かるので、ユーザーテーブルから「Y0001」のユーザーを探すことで「Y0001」のユーザーの名前と住所を取得することができます。

そして、ユーザーの名前や住所が変更になったとしても、ユーザーテーブルから該当する1行を修正するだけで済みますし、注文テーブルには一切変更が発生しません。

さて、もう一つ分離しておきたいカラムがあります。
購入商品と単価です。

表5

これも商品名や単価に変更があった場合、すべてのデータを修正することになってしまいます。
そこで同様の手順で、商品テーブルとして分離します。

表6

注文テーブルについて、だいぶスッキリしましたが、一人が複数商品を購入する場合、以下のように同じようなデータが並んでしまいます。

表7

データベースとしては、注文番号は一つのデータ(1行)を表すべきなのに、複数行に分かれてしまうのは、よくありません。

ただし、先程までのように、分離させるところはもうありませんね。

ここで、一度注文テーブルと商品テーブルとの関係性に注目してみましょう。

注文番号「1」に対して、商品ID「I0001」「I0002」「I0003」の3つが紐づいています。

逆に商品IDを基準に見てみると、例えば商品C(商品ID:I0003)は、注文番号「1」「2」「3」と紐づいてます。

つまり注文番号と商品IDは、お互いに自分自身のデータ一つにつき、複数のデータと紐づく関係にあります。(ちなみにこれを「多対多の関係」と言います。)

多対多の関係にあるカラムが存在したときに、このようなテーブルが出来上がってしまいます。

本題に戻りますが、これを解決するために、「中間テーブル」を作ります。

中間テーブルでは、注文番号と商品IDの紐づけを行うのが目的です。

表8

このように、中間テーブルを見に行けば、どの注文にどの商品が紐づいているのかを見ることができますし、注文テーブルもスッキリさせることができました。

ここまでの流れを「正規化」と言います。「第1正規形〜第3正規形」はこのような縦横方向の繰り返しをなくすように設計していくこと、と考えれば少しとっつきやすくなるかと思います。

完成形
表9

ER図を書いてみる

ここまで書いてきたことをER図に書き起こします。
ER図

ちなみにこちらは、「Draw.io」というサービスで作成しました。
VSCodeにプラグインがあるため、VSCode上で上記のようなER図を比較的作成することができます。

https://www.drawio.com/

分離されたテーブル同士を紐付けることを表すために、以下のような書き方でテーブル同士をつなぎます。

リレーション一覧

どんな関係が1対多だったっけ?ってなる方は、以下の記事がとても分かりやすかったので参考にしてみてください。
https://qiita.com/ramuneru/items/32fbf3032b625f71b69d

ポイントを一言で言えば、「自テーブルの一つのデータに対して、相手テーブルのいくつのデータが紐づく可能性があるか?」です。
これを考えていけば、理解できるようになるはずです。

まとめ

  1. まずは必要なデータを表にまとめる。(サンプルデータも入れましょう)
  2. 繰り返しているところを見つけ、分離させる。
  3. 多対多の関係性にあるものは中間テーブルを作成する。

このように考えていけば、意外と簡単に感じられるかもしれません。

もちろん、正規化の理論的な部分が不必要なわけではありませんし、この記事のやり方では不十分なところは多々あるとは思います。

それでもデータベースをこれから学習する人が、少しでもデータベースに親しみを持てるようにと思い、本記事を作成しました。

GitHubで編集を提案

Discussion