« 家計における「資本勘定」とは(後編) | トップページ | 「お風呂本」は気宇壮大をもってよしとす »

2006.04.08

データモデル上の「行番号」とは何か

 一般にデータ項目は、その定義域を規定するための、自身を識別子とするテーブルを伴う。実際にはそのようにデータモデルが示されることはあまりないが、この原則を理解しておくことは重要だ。これを知っておけば、不自然なデータ項目とみなされがちな「明細行番号」の意味もわかる。

◆「現在庫数量テーブル」を示す必要はない

 あるテーブルの識別子が別のテーブルの識別子の一部に取り込まれていれば、2つのテーブルの関係を親子関係とみなし、前者を親、後者を子と呼べる。典型的な例が「在庫」まわりのモデルだ。この場合なら、「商品」と「倉庫」が親で、「在庫」が子である。

Imagez1

 ここで、次のようなモデルを考えてみる。あるテーブル上の識別子に含まれない項目(属性項目)が別のテーブルの識別子となっている場合、それらのテーブルは参照関係にあるといい、この場合ならば「現在庫数量」のテーブルが「参照先」で、「在庫」が「参照元」である。在庫まわりのデータベースに慣れている人なら、このモデルは異様に見えるだろう。

Imagez2

 しかし、これを次のように無意味な文字を使って形式化すれば、モデルとしてはごく普通に見える。Gのテーブルが属性項目を持たない点が変わってるように見えるかもしれないが、このような構造は現実にあり得る。印刷済みの申請用紙などに固有な識別番号が印字されている場合、その識別番号を管理するためのテーブルが属性項目を含まないことはある。

Imagez3

 では、「現在庫数量テーブル」がモデリングされたり実装されたりすることが実際にはないのはなぜだろう。それは「現在庫数量」のデータ項目が意味的に特殊であるからではなく、その項目向けの「定義域(ドメイン)」を規定するためにテーブルを用意する必要がないからだ。

 この「現在庫数量テーブル」には、現在庫数量の値として0から9,999,999までを登録することを想定している。しかしそんなテーブルは誰も実装しないし、1000万件のレコードをわざわざ登録することもしないだろう。なぜなら、現在庫数量が取り得る値については「7桁の整数」という形式でDBMSに簡単に指示できるからだ。

◆定義域を規定する2つの方法

 このように、そのテーブルが識別子に関数従属する属性をいっさい持たず、かつ、識別子が取り得る値をデータタイプとして容易に規定できるようであれば、「一般にデータ項目はその定義域を規定するために、その項目を識別子とするテーブルを伴う」という原則をショートカットできる。

 しかし、このショートカットはDBMSの基本機能のおかげでもある。もし極端に非力なDBMSがあって、「文字」とか「数字」とか「ブーリアン」とかいった単純なデータタイプさえ扱えないとしたら、「現在庫数量テーブル」もモデルに載せて、実装しなければいけない。データモデルが「実装独立」であることが破綻するような話ではあるが、極端にいえばそういうことだ。

 反対に、複雑なデータタイプをユーザが定義して指定できるような強力なDBMSを用いたとしても、次のようなテーブル(傷病別忌避薬)はどうしても実装しなければならない。属性をともなわないとしても、データ項目が取り得る値の組み合わせを規定するために、この種のテーブルは必要だ。

Imagez4

 というわけで、定義域を規定する方法には、データタイプを指定するやり方と、テーブルを設けるやり方の2つがある。ただし、定義域をデータタイプで規定できるというのは、それが単独項目であり、しかもデータタイプとして取り得る連続的な値をとるものであるからだ。複数項目の組み合わせにもとづく定義域については、テーブルを導入して積極的に管理する必要がある。いわゆる第四正規形や第五正規形は、そこらへんの問題をとりあげたものだ。

◆「行№テーブル」を示す必要はない

 さて、初心者向けにDB設計を説明した書籍などで、受注明細のモデルが次のように示されることがある。しかし、現実にこのように設計されるケースは少ない。なぜなら、このモデルでは「ひとつの受注において、同一商品向けの明細行を複数保持できない」という特殊な制約を盛り込むことになるからだ。

Imagez5

 まあそのような制約が業務上歴然と存在するのであればべつだが、現実には同一商品の明細行が複数混在する可能性はよくある。受注明細上に載っている「納期」などが異なった形で、同一商品が複数行で指定されるケースなどだ。というか、「ひとつの受注において、同一商品向けの明細行を複数保持できない」という制約を組み込むべき積極的な理由がないことのほうが多い、と言うべきかもしれない。そんなわけで、次のように設計されることのほうが多いし、無難である。

Imagez6

 このモデルに対して「行№なんていかにも作為的な項目で識別子を作るなんて納得できない。識別子を{受注№+商品C}にすれば、2つの親が揃うので形式的にも自然だが、{受注№+受注行№}だと"片親"になってしまうのも不自然だ」と批判されることがある。

 筆者に言わせれば、「受注№」も「受注日」も「受注数量」も、実世界を恣意的に分節した結果という意味で「作為的で不自然な項目」である。モデリングとは、実世界を写実する行為ではなく、現実とうまく折り合いをつけるための「使いやすい幻想」を組み立てる行為でしかない。

 まあその議論はさておいて、「行№」を識別子に組み込むやり方の正当性については次のように説明できる。「行№」の定義域をデータ項目として簡単に指定できるし、この項目に関数従属する属性項目もたまたま存在しない。ゆえに、「受注行№テーブル」を次のようにわざわざ示す意味がない。そのように理解すれば、「行№」もありきたりな項目のひとつであることがわかる。

Imagez7

|

« 家計における「資本勘定」とは(後編) | トップページ | 「お風呂本」は気宇壮大をもってよしとす »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: データモデル上の「行番号」とは何か:

« 家計における「資本勘定」とは(後編) | トップページ | 「お風呂本」は気宇壮大をもってよしとす »