「データベース設計論」を読む(3) -- ここが理解できないうちはサブセットは使えない


T字形でnullを排除する方法に、「形式的サブセット」の導入がある。

形式的サブセット

顧客マスタに「携帯電話番号」を置くと、携帯を持っていない人の同属性がnullになってしまう。
(まあ、nullにしないで空文字列でも入れておけばいいのかもしれないが*1
そこで、nullを回避するために、顧客マスタを「携帯所有者」「携帯非所有者」に分割する:

携帯所有者 = { 顧客番号, 顧客名, 携帯電話番号 }
携帯非所有者 = { 顧客番号, 顧客名 }

という例がデータベース設計論 T字形ER―関係モデルとオジブェクト指向の統合をめざして P-100に出てくる。
これをそのまんまの意味に受け取ると非常に困ったことになる。
FAX番号とかメールアドレスとか、顧客が持ってたり持ってなかったりするものが他にもあったらどうするか。
いちいちサブセットに分割していくと、収拾がつかなくなる。
携帯とFAXとメールアドレスの所持はそれぞれ直交しているので、全てをサブセットの階層で表現しようとしても無理。「階の交叉」が発生してしまう。
<実質的>サブセットの階の交叉の解消方法の例はここに示されているが、
http://www.sdi-net.co.jp/tm-note-20041216.htm
null回避のための<形式的>サブセットが交叉した場合の対処法はどこにも書かれていないと思う。


この点について去年からずーっと考え込んでいたが、なんと言うか、あんまり難しく考えないで、VEで解決していいんじゃないの、という気になってきた。
上記の例ならこうなる:

顧客マスタ(R) = { 顧客番号, 顧客名 }
顧客携帯電話(VE) = { 顧客番号, 携帯電話番号 }

実際、P-156の「応用編1 電話番号」では、上記と同じVEで解決するモデルが描かれている。
で、こうコメントされている:

P-156
一般の営利企業は、電話をVEとして扱うのが適切である。
ただし、「実装形」として、VEの電話番号は、顧客(マスタ)の中に戻して実装される
かもれしない。

ここが分かるまでサブセットは使えない

サブセットというのはT字形ER手法の肝だと思う。
T字形ER手法は、外部キー制約というRDBの重要な機能の使用を放棄(否定?)しているのだが、それはサブセットを実装したいからではないかと考えている。
実際、正美氏は去年の研修で「顧客には外部キー制約を使用しないように指導している」と語っていた。
その場ではその理由には触れていなかったが、想像するに

  • データロードの速度保証のため
  • サブセットの使用により、外部キー制約が付加できないため

ではないかと思う。


受注ヘッダが、顧客番号を外部キーとして参照している場合、顧客マスタが「携帯所有者」「携帯非所有者」の2テーブルに別れていたら、
こんな感じで外部キー制約をつけることはできない。

create table 受注ヘッダ (
  受注番号 lnt8 not null primary key,
  顧客番号 int8 not null references ???(顧客番号)      <--参照先テーブル名が特定できない
    :
);

トリガーを使えば制約の代用品は作れるのだろうが、やりたくないなあ。
あと、顧客マスタとは別に、顧客番号のみを管理する「顧客番号マスタ」を作成すれば

  顧客番号 int8 not null references 顧客番号マスタ(顧客番号)

とできるが、そんなことするかなあ。
外部キー制約なんてやめましょう、と社内の人に言えるほど説得力のある根拠が見つかるまでは、サブセットを実装するのはやめようと思う。


ところで、今年に入ってから付き合いのできた取引先が、やはり「外部キー制約は使わない派」なのだ。
何でそういう設計になっているのか、はっきりしたことは教えてもらっていないのだが、ほんとに外部キー制約なんて、無くてもいいものなのだろうか?

*1:その場合は携帯電話番号にunique制約は付けられなくなることに注意