本文へスキップ
BecomeCoder

SQL データ操作 (DML)コース · 第0章 データベースってなに? · レッスン0-4

なぜ表を1つにまとめないのか ― キーと正規化の入口

ブラウザで完結

導入

「注文を見るなら、会員名も商品名も1つの大きな表にまとめておけば楽なのでは?」と思うかもしれません。ところが実際の DB は、あえて意味ごとに表を分けて持ちます。このレッスンでは、その理由と、表どうしをつなぐ「キー」という考え方を実物で確かめます。

説明

このショップの DB は、会員 users・注文 orders・注文明細 order_items・商品 products などに分かれています。まず注文 orders を見てください。

SELECT * FROM orders;

「誰の注文か」は user_id(会員の番号)だけで表され、名前は入っていません。もし1つの大きな表に「注文ごとに会員名・年齢・都市まで全部」を書いていたら、どうなるでしょう。佐藤さんは何度も注文しているので、名前も都市もそのたびにコピーされます。

悪い例:1つの表にまとめた場合namecity が重複する)

order_idnamecityproduct
1佐藤東京キーボード
2佐藤東京モニター
佐藤東京

もし佐藤さんが大阪へ引っ越したら、太字の city を全部直さないといけません。1か所でも直し忘れれば、「東京の佐藤」と「大阪の佐藤」が混在してデータが食い違います。注文が増えるほど、この危険は膨らみます。

良い例:意味ごとに表を分ける(佐藤の情報は1か所だけ)

会員の情報は users に一度だけ置き、orders は「誰の注文か」を番号 user_id で指すだけにします。佐藤さんが引っ越しても、直すのは users のたった1行で済みます。

flowchart LR
    U["users(会員)<br/>id・name・age・city"]
    O["orders(注文)<br/>id・user_id・ordered_at"]
    U -->|"1人が何度も注文する<br/>users.id = orders.user_id で対応"| O

このとき、各行を一意に識別する番号 users.id主キー(primary key)、それを別の表から指し示す orders.user_id外部キー(foreign key) と呼びます。

flowchart LR
    PK["主キー(primary key)<br/>users.id … 各会員をただ1つに特定する目印"]
    FK["外部キー(foreign key)<br/>orders.user_id … 他の表の主キーを指す"]
    FK -->|"参照する"| PK

そして、いまやったように「重複が出ないよう意味ごとに表を分ける設計」を 正規化(normalization) といいます。こうして表どうしを関係(リレーション)でつなぐ仕組みだから、この種の DB を リレーショナルデータベース(RDB) と呼ぶのでした。分かれた表は、後の章の JOIN でいつでもつなぎ直せます。

やってみよう

SELECT * FROM users;SELECT * FROM orders; を順に実行し、ordersuser_idusersid を指していることを見比べてください。たとえば user_id が 1 の注文は、usersid が 1 の人(佐藤さん)のものです。

演習

会員のうち id が 2 の人が「誰なのか」を、users テーブルから確かめてください(WHERE を使います。文法は次章で学ぶので、下のヒントをそのまま使って構いません)。

ヒント1を見る

SELECT * FROM users WHERE id = 2; を実行すると、id が 2 の1人だけが出ます。

実際に動かしてみよう

下のエディタにクエリを書いて「実行」を押すと、ブラウザ内のSQLiteで結果が表示されます。本文の例をそのまま試したり、書き換えたりしてみましょう。

SQL — ブラウザ内で実行(SQLite)

ブラウザ内でSQLを動かす環境(SQLite)を読み込みます(初回のみ一瞬)。
スクロールして表示された時点でも自動で読み込まれます。