RDBにおける正規化(第一正規化)
第一正規化
1つのマスには1つのデータのみを置くこと。
ひとつのマス(ここでは便宜上そう呼びます)に1つの値が入っている場合、その値はスカラ値と呼ばれるそうです。
正しくない例
記事ID | 記事タイトル | タグ |
---|---|---|
A001 | 初めまして | |
A002 | 沖縄旅行 | 日記 旅行 買い物 |
A003 | 食事を作りました | 日記 料理 |
この例ではタグというカラムに値が0~3つ入っています、アウト。
このようなことはRDBの第一正規化においては許されることではありません。
しかし、その通りにすると、この例でいうタグは記事に対して一つずつしか許されないことになってしまいます。
なぜ許されないのか?
マスにいくつか数字が入ってる(つまり配列等になっている)ばあい、主キーを選ぶとレコードの各マスの値を一意に決定できなくなってしまうからです。
これはRDBとしてはあるまじきことで、RDBにおいてはすべての正規化において、Aを決めるとBが一意に値が定まるという大事なルールがあります。(Aは例えば主キーや何らかの組み合わせ、Bはその戻り値)
戻り値は一つでなければなりません、配列が返ってくるとどれが目当てのデータなのかもわかりません。
しかし、実際のところ上の例のようなデータの構造を扱いたい場合があります。
どうすれば許されるのでしょうか?許される方法を考えてみましょう
方法その1、なんか沢山カラムを増やしまくる
記事ID | 記事タイトル | タグ1 | タグ2 | タグ3 |
---|---|---|---|---|
A001 | 初めまして | |||
A002 | 沖縄旅行 | 日記 | 旅行 | 買い物 |
A003 | 食事を作りました | 日記 | 料理 |
なんか色々あほっぽいですが一応実現は出来ます。
でも、見るからに問題が多そうです、例えば現状タグ上限3つまでとか。
他の方法を考えましょう。
方法その2、タグの数だけレコードを増やしてみる
記事ID | 記事タイトル | タグ |
---|---|---|
A001 | 初めまして | |
A002 | 沖縄旅行 | 日記 |
A002 | 沖縄旅行 | 旅行 |
A002 | 沖縄旅行 | 買い物 |
A003 | 食事を作りました | 日記 |
A003 | 食事を作りました | 料理 |
この方法で達成したか?と思うのですが、まだです。主キーが決められない問題が発生します。
主キーを無理やり決める場合、記事ID、記事タイトル、タグの3カラムすべて指定することが必要になりますが、そうするとA001のようにタグを持たない記事は残念ながら主キーにNULLは含めないのでアウトです。
では空マスに「タグ無し」を入れるという方法ではどうか?というとそれもマズいです。
なぜか?
そもそもタグって日記と分けて考えるほうが自然ではありませんか?
だって日記は1つずつ、タグはそれにいくつかくっつく。でもタグ自体はその日記固有のものではなく、同じものが他の日記にもくっついたりしています。
たとえるならば、会社に勤めている人がいたとして、その人は会社の一部だ!と言っているようなものです。家に帰ると家の一部だと言われます。それってもはや人という存在が別にあると考えたほうが、当たり前ですが、分かりやすくないですか?
つまりタグと日記は別々の存在であるはずです。
つまりこれではいまいちテーブルの意味が分かりづらく、レコード一つ一つが何なのかもピンときません。これではタグが主体なのか日記が主体なのか…そもそも何が主体とか言ってる時点でおかしな話なのです。1つの存在について語っているわけですから。
別の方法を考えましょう。
方法その3、テーブルを分ける
テーブル1つしか使ってはいけないなんて誰が言った!
そうです、テーブルをいくつか使えばいいんです。
記事テーブル
記事ID | 記事タイトル |
---|---|
A001 | 初めまして |
A002 | 沖縄旅行 |
A003 | 食事を作りました |
タグテーブル
記事ID | タグ |
---|---|
A002 | 日記 |
A002 | 旅行 |
A002 | 買い物 |
A003 | 日記 |
A003 | 料理 |
これで、上の問題は解決しました。 あとは様々なアプローチでこのテーブルを利用するだけです。