導入
「注文を見るなら、会員名も商品名も1つの大きな表にまとめておけば楽なのでは?」と思うかもしれません。ところが実際の DB は、あえて意味ごとに表を分けて持ちます。このレッスンでは、その理由と、表どうしをつなぐ「キー」という考え方を実物で確かめます。
説明
このショップの DB は、会員 users・注文 orders・注文明細 order_items・商品 products などに分かれています。まず注文 orders を見てください。
SELECT * FROM orders;
「誰の注文か」は user_id(会員の番号)だけで表され、名前は入っていません。もし1つの大きな表に「注文ごとに会員名・年齢・都市まで全部」を書いていたら、どうなるでしょう。佐藤さんは何度も注文しているので、名前も都市もそのたびにコピーされます。
悪い例:1つの表にまとめた場合(name・city が重複する)
| order_id | name | city | product |
|---|---|---|---|
| 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; を順に実行し、orders の user_id が users の id を指していることを見比べてください。たとえば user_id が 1 の注文は、users の id が 1 の人(佐藤さん)のものです。
演習
会員のうち id が 2 の人が「誰なのか」を、users テーブルから確かめてください(WHERE を使います。文法は次章で学ぶので、下のヒントをそのまま使って構いません)。
ヒント1を見る
SELECT * FROM users WHERE id = 2; を実行すると、id が 2 の1人だけが出ます。