県と市町村を属性に持つ顧客マスタは非正規形


新人研修で正規化理論を解説しなきゃならないので復習してみたが、やっぱり実践との関係がよくわからない。
例えば第三正規形の定義は

  • 第二正規形である
  • すべての非キー属性が、キーに対して推移従属していない

だと思うんだけど、であれば次のような顧客マスタは非・第三正規形ということになるよな。

  顧客マスタ = { 顧客番号(PK), 顧客名, 住所(県), 住所(市町村), ... }

市町村が決まれば県が一意に定まるので、

顧客番号 → 市町村 → 県

という推移従属が成り立つ。よって上の顧客マスタは非正規形である。
... という理解でいいのかな。

正規化しなくても困らない場合がある

上の顧客マスタの推移従属を解消するには

  顧客マスタ = { 顧客番号, 顧客名, 住所(市町村), ... }
  住所マスタ = { 住所(市町村), 住所(県) }

に分解することになるが、現場でこんなことする人が居るだろうか。
正規化とは更新時異状の回避のためにやることだ。住所マスタを分離することで回避できる更新時異状とは

  • 挿入時異状 まだ顧客の居ない {市町村,県} を登録できない
  • 削除時異状 その市町村に住む唯一の顧客を削除すると {市町村,県} が消滅する
  • 修正時異状 その市町村に住む唯一の顧客が引っ越すと、引越し前の {市町村,県} が消滅する

等だが、上記の異状が問題になるかどうかはアプリケーションの要件による。住所マスタを維持すべき要件がないなら、「非正規形」であっても問題はない。

TMならどうする

推移従属を含むリレーションには、正規化すべきデータとそうでもないデータがあることが分かったが、同業の方々はここをどう考えているのだろう。
恐らく現場のエンジニア達は、正規化理論を参照しつつも野生の勘を発揮して正規化を行い、必要以上に分解することを無意識のうちに避けている。
たぶん { 顧客番号, 顧客名, 都道府県, 市町村 } が非正規形だと思ってない人も多いんじゃないか。自分がさっき気付いたから言うんだけど。


最後にTMならどうするかを書いて締める。
TMなら

  • 県を区分コードと見て、元の形のままにするか、
  • 県をresourceと見て、住所を顧客と県の対照表と見るか、
  顧客マスタ = { 顧客番号, 顧客名, ... }
  都道府県マスタ = { 県名 }
  顧客.住所 = { 顧客番号(R), 県名(R), 住所(市町村) }

どちらかにするのが正解だと思う。いずれにしても正規化理論のように顧客マスタ・住所マスタに分解することはない。