コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
正規化とは何か
社名が変わって、198 行だけ直した
取引先の会社名を、請求データの各行にそのまま書いている表があるとします。同じ会社名が 200 行に散らばっています。
その会社が社名を変えました。担当者は古い社名を条件にして一括更新をかけ、198 行が書き換わります。残った 2 行は、入力したときに空白が 1 つ多く入っていたせいで条件から漏れました。エラーは出ていません。半年後、その 2 件だけ古い社名の請求書が出て、先方から連絡が来ます。
| 請求 ID | 会社名 | 担当者 | 金額 |
|---|---|---|---|
| 1 | 山田商事 | 佐藤 | 50,000 |
| 2 | 山田商事 | 佐藤 | 30,000 |
| 3 | 鈴木物産 | 田中 | 80,000 |
同じ事実が 200 か所に書き写されているとき、それを正しく保つ責任は書く側のコードにあります。1 か所でも取りこぼせば、どれが本当の社名なのか誰にも分からなくなります。
厄介なのは、食い違ったまま入っていても DB が何も言わないことです。同じ会社の行に違う社名が書いてあっても、表の上ではただの文字列が 2 種類あるだけで、矛盾としては扱われません。
まだ取引していない会社は、登録すらできない
同じ表からは、別の困りごとも出てきます。
新しく取引先を登録したいのに、その会社の請求はまだ 1 件もありません。会社を入れる場所が請求の行しかないので、金額も担当者も空のままの行を作るしかない。逆に、鈴木物産の唯一の請求を取り消すと、その行と一緒に会社の情報まで消えます。
会社の情報を置く場所がない、というのが根っこの原因です。書き換えのときに起きるのが更新の異常、追加のときに起きるのが挿入の異常、削除のときに起きるのが削除の異常で、3 つとも同じ 1 つの表から出ています。
気づきにくいのは、この 3 つが別々の不具合に見えることです。取りこぼしはコードの書き方の問題に見え、空の行を作る話は運用の都合に見え、消えた会社はうっかりに見える。担当者も時期も違うので、同じ原因だと誰も気づかないまま、それぞれに小手先の対処が入っていきます。
「決まれば、決まる」を矢印で書き出す
どこが冗長なのかは、感覚ではなく機械的に見つけられます。列と列の間に「これが決まれば、これも決まる」という関係を書き出すのです。
プレーンテキスト
会社 ID --> 会社名
会社 ID --> 会社の住所
請求 ID --> 金額会社 ID が決まれば会社名は 1 つに決まります。ところが表の上では、同じ会社 ID の行に違う会社名を書き込めてしまう。決まるはずのものが、書く場所の数だけ自由になっている。これが冗長の正体で、先ほどの 3 つの異常はすべてここから出ています。
先ほどの表なら、直し方はこうなります。会社の表を別に立てて、社名と住所はそこに 1 行だけ置く。請求の表からは社名を消し、会社 ID だけを残す。社名の変更は 1 行の書き換えで終わり、取りこぼす行がそもそも存在しなくなります。まだ請求のない会社も登録でき、最後の請求を消しても会社は残ります。3 つの異常が同時に消えるのは、原因が 1 つだったからです。
この矢印に沿って表を分け、決まる側の値を 1 か所だけに置き直す手続きが正規化です。分け方には段階があり、1 つのセルに複数の値を詰めない、主キーの一部だけで決まる列を切り出す、主キー以外の列で決まる列を切り出す、と順に進みます。その先にもボイスコッド正規形や第 4 正規形といった段階がありますが、実務で手を動かすのは 3 段目までです。