STAGE 05 — 5-1 / テーブルの結合

なぜテーブルを分けるのか

考えてみよう

もしアマテラスの「任務(ミッション)」を1枚の表にまとめるとして、そこに担当する乗組員の名前・役職・年齢・出身地・給与まで、全部いっしょに書き込んだとしたら——何が起きるでしょう?

同じ乗組員が2つ、3つと任務を担当したら、その人の情報が表の中で何度も繰り返されることになりますよね。少し想像してから読み進めてください。

1枚の巨大表に、任務と乗組員を全部詰め込むと

ためしに、任務(ミッション)の表に、担当する乗組員の情報を全部いっしょに書き込んでみましょう。

titlecrew_namecrew_rolecrew_homecrew_salary
火星資源調査ケンジパイロット火星400000
タイタン氷床探査ソラエンジニア470000
エウロパ生命探査レイ研究員火星380000
火星気象観測ケンジパイロット火星400000

4行目に注目してください。ケンジがまた別の任務を担当したので、「ケンジ・パイロット・火星・400000」という同じ情報が、もう一度そっくりそのまま書かれています。任務が増えるたびに、こうした重複がどんどん積み重なっていきます。

重複が引き起こす「更新漏れ」

この状態で、ケンジの給与が400000円から420000円に上がったとしましょう。表の中にケンジの行が2つあるので、両方とも書き換えなければなりません。

もしうっかり1行だけ直して、もう1行を直し忘れたら——同じ「ケンジ」なのに、行によって給与が違うという、おかしなデータになってしまいます。これが更新漏れです。任務が10件、100件と増えていけば、直し忘れが起きる可能性はどんどん高くなります。同じ情報をあちこちに重複して持つこと自体が、事故の種なのです。

テーブルを分ける発想

この問題を解決する考え方はシンプルです。乗組員の情報は乗組員の表に1回だけ書き、任務の表には「誰が担当か」を示す番号だけを持たせます。

crew テーブル(乗組員):

idnameroleagehomesalary
1ユミエンジニア24地球320000
2ケンジパイロット35火星400000
3サクラ医師41地球520000
4ハルト医師33450000

missions テーブル(任務):

idtitlecrew_idplanet_idrewardstatus
1火星資源調査2150000完了
5金星大気観測1240000待機
8ケレス医療支援4565000進行中

missionsテーブルの crew_id は、crewテーブルの id を指す数字です。crew_id = 2 は「crewテーブルのid=2、つまりケンジ」を意味します。これで、ケンジの給与が変わってもcrewテーブルの1行だけを直せば済みます。missions側には給与そのものが存在しないので、直し忘れも起こりようがありません。

外部キー ― 他の表の行を指し示す番号

この crew_id のように、別のテーブルの主キー(id)を指し示す列のことを、外部キー(Foreign Key)と呼びます。missionsテーブルにとって、crew_id はcrewテーブルへの、planet_id はplanetsテーブルへの外部キーです。

外部キーは、いわば「この情報の続きはあちらの表にありますよ」という案内板。表と表が、この案内板でつながっているおかげで、重複を持たずに済んでいるのです。

正規化のさわり

「重複を持たず、関連する情報は外部キーで参照する」——この考え方に沿って表を設計していく作業を、専門的には正規化と呼びます。細かいルールはこの先の学習で少しずつ触れていけば十分で、今は「同じ情報は1箇所に。あとは番号でつなぐ」という感覚さえつかめれば合格です。

確認問題

1枚の巨大な表に全部の情報を詰め込む代わりに、crewテーブルとmissionsテーブルに分けることの、いちばんのメリットは何でしょう?

答えを見る

同じ情報(乗組員の名前や給与など)を1箇所にしか持たなくて済むことです。情報が1箇所にしかなければ、更新するときに直し忘れが起きません。

missionsテーブル側は crew_id という外部キーでcrewテーブルの行を指し示すだけなので、任務が何件増えても乗組員の情報が重複することはありません。

ゆみちゃん
ゆみ

表を分けるのは、面倒なことをするためじゃなくて、むしろラクをするための工夫なんだよね。「同じ情報は1回だけ書いて、あとは番号でつなぐ」——このイメージさえ持てればOK! 次回はいよいよ、番号でつながった表同士を、実際にSQLでくっつける「JOIN」を学ぶよ。

SQL DIVERのゲーム画面でも、まさにこのcrewテーブルとmissionsテーブルが分かれた形で登場します。次回学ぶJOINを使って、この2つの表をつなげるところから、SQL DIVERでの実践がぐっと面白くなっていきます。