第七回 データベースよもやま話

(1)数値型か?テキスト型か?


皆さんの中で、実際にAccessを使ってテーブル設計をなさった経験のある方も、いらっしゃると思います。

テーブル設計を始めて、まず最初に突き当たるのが、この「数値型か?テキスト型か?」という問題です。もう少し具体的に言いますと、それはレコードのID、すなわちキーコードの「型」のことです。テーブルのフィールドの中で、例えば人の名前は「テキスト型」でなければならないし、商品の値段は「数値型」でなければならない、ということは、誰しも予想することができます。しかしキーコードはどうでしょうか?

データベースのレコードは「一意性」を持つ、すなわち「他に同じ物がない」状態でなくてはならない、ということをお聞きになったことがあると思います。例えば、たまたま同じ住所にお住まいの「山田太郎」さんという人が二人いた場合、名前と住所では別人であることの「判別」は不可能です。でも、この二人に別々のコードが付けられていれば「別人」であることを認識出来るわけです。逆に、このお二人が、実は同一人物であって、担当者がたまたま誤って別のコードをつけてしまった、などということも、もちろんありえます。その場合は、その他のフィールドデータ、例えば「電話番号」「家族構成」「勤め先」などから類推して、あるいはご本人に確認するなどして、同一であることが確定したならば、片方のデータを「削除」すべきでしょう。

話を本題に戻したいと思います。それではキーコードは、数値型にしたらよいのか?テキスト型にしたらよいのか?というおはなしですが、結論から言うと「どちらもありうる」ということになります。それどころか、ひとつのデータベースの中で、その両方を「使い分ける」ことさえ可能です。ただし、そのようにどちらもありうる中で、なお私の意見を申し上げるならば「数値型になさい」ということになるかと思います。

これから、この数値型・テキスト型のデータとしての違いを少し説明しますが、難しい内容は一切省きます。その「現象面」から、二つの型の違い、のみを見ていきたいと思います。その前提として、キーコードの「最大唯一の目的」が、レコードに「一意性を持たせること」である、ということをまずご念頭においていただきたいと思います。極論すれば、キーコードの持つ意味は、これ以外ないといって過言ではありません。では数値型から見ていくことにいたしましょう。

<数値型>

基本的には「1」から順番にコードを振っていくことになります。「2」「3」「4」・・・とキーコードを振り分けていくことになります。

ここで皆さんの中にハタと気がつかれる方が、いらっしゃるとおもいます。「1」~「360」というように「桁数」がばらばらになる、のではないかというふうに。そうなのです、基本的に数値型では、このような表示になってしまいます。そして誰しも思うのは「一覧表」等のレポートに印刷した場合の「見栄え」の問題です。表の見栄えを良くするためには、桁数が揃っていたほうが良いと、誰しも思うことでしょう。でもご安心ください、解決方法はあります。テープル、フォーム等の書式プロパティを「000000」とすることによって「1」を「000001」と6桁で表示することができるのです。ですから「桁数」表示は、あとからいくらでも増やすことが出来ます。この点については問題ありませんので、ご安心いただきたいと思います。

また、テーブルやフォームのプロパティを変えずとも、コードの桁数を統一する方法は、実は他にもあります。キーコードそのものを、最初から6桁にするのです。コードの初期値を「100001」とすれば「100002」「100003」・・・と増やしていって、最終的には「999999」までは、6桁のコードを確保できます。データの最大予想数にあわせて(例えば顧客コードの場合)100万代から始める、というようにするわけです。

データの数というものは、その種類によって自ずから「最高数値」の予想はつくものです。例えば社員コードの数は、どんな大会社であっても、せいぜい多くて5桁もあればよいでしょう。小さな会社であれば2桁で済む場合だってあります。それに対して、顧客コードはどうでしょうか?6桁で足りなくなる可能性は、ゼロではありませんね。顧客コードはなるべくコードの桁数を、多めにとっておいたほうが「無難」です。商品コードなども「多品種少量」業種の場合、桁数を多めににとっておくべきでしょう。逆に部署コードなどはせいぜい4桁もあれば足りるでしょう。

<テキスト型>

さて、テキスト型です。テキスト型の利点(同時に欠点でもあるのですが)は「文字列や記号を併用できる」ということにあります。たった今「利点」と申し上げましたが、実のところ、私には欠点のほうがはるかに多いと思われます。

実際問題、文字列キーコードが要求される最大の理由は、カスタマーが「それまでコードに文字列を用いていたから」ということが挙げられます。つまり先方が、システム構築にあたって、従来の業務フローを「見直す」ことなく、そのまま「踏襲」することを主張なさり、そこを押し切られるような場合です。笑い話のような事実なのですが、ある会社では、社員番号の最初に「役職」を表すアルファベットを付けていた。どういうことかといえば、昇進するたびに「社員コード」が変わる(笑)。これはもう、メチャクチャです。

唯一、それもありかな?と、私が思うのは「商品コード」の場合です。各社が取り扱う商品の「シリアル番号(ないしは型式)」というのは、言うまでもなく、既に「一意性」をもたせているわけです。そしてそういった会社では、シリアル番号を、識別の基準として普通に用いているわけです。そうなってくると、シリアル番号そのものをキーコードにしてもよいかな?という考えも、頭を過ることになります。ただし、その条件としては、シリアル番号の管理そのものが、よほど厳重になされている必要があります。重複は許されません。

シリアル番号には、アルファベット、ハイフン、かぎかっこ等々、ありとあらゆる「文字列」が使用されます。そうなると、キーコードはテキスト型である必要が生じます。

こう申し上げると、私が商品コードにはシリアル番号を用いることを積極的に「容認」しているではないか、と思われるかも知れませんが、そうではありません。基本はあくまでも、シリアル番号とは別に、キーコードをつけて、それを「数値型になさい」というのが私の考えです。

データベースの目的のうち重要なもののひとつに、いろいろな条件でデータを抽出したり、並べ替えたりというものがあります。その条件となりうるフィールドは、ぜひともキーコード以外とすべきです。キーコードに「一意性」以外の「意味」「属性」を持たせることは、絶対にしてはなりません。そのためにはキーコードは、基本的に「数値型」にすべきなのです。

最後に「蛇足」になりますが、文字列を並べ替えたときには、説明のできないことが起きることがあります。次の図は、文字列のキーコードを試しに「昇順」に並べ替えたところです。

文字列のキーコードを試しに「昇順」に並べ替えたところ

これを見ると「辞書」的な意味での「並び」の優先順位は「①記号→②数字→③文字」の順番であるように見えます。ところがもしそうだとすると、私は最後の二つは並びが「逆」のような気がするのですが、如何でしょうか?このことが何を意味するかといえば、本当に厳密な「昇順」「降順」を表示するためには、キーコードに文字列を使用することによってではなく、フィールドに「フリガナ」を設けるのが最良である、ということになります。何を申し上げたいかといえば、上記の商品コードです。やはり商品テーブルを作る場合「商品コード」「シリアル番号」「商品名」「商品名のフリガナ」というのが、理想的ではないでしょうか。

(2)DateDiff関数

このページのトップへ

アクセスは、色々と便利な関数を用意してくれています。しかし、ときどきあれっ?と思うような関数に出会うことがあります。今日はその中の一つ「DateDiff」を取り上げてみようと思います。「DateDiff」関数は、二つの日付の間の差、すなわち年数・月数・日数を計算してくれます。以下の例ではそれぞれのTextBoxには次のような関数が入っています。日付の入ったTextBoxは、それぞれ「開始日」「終了日」です。

日数=DateDiff(“d”,[開始日],[終了日])

週数=DateDiff(“w”,[開始日],[終了日])

月数=DateDiff(“m”,[開始日],[終了日])

年数=DateDiff(“yyyy”,[開始日],[終了日])

開始日、終了日をそれぞれ「2014/01/01」「2014/01/07」と入れてみました。

開始日、終了日をそれぞれ「2014/01/01」「2014/01/07」と入れてみました。

開始日、終了日をそれぞれ「2014/01/01」「2014/01/31」と入れてみました。 予想通り、週数も切り捨てされています。

開始日、終了日をそれぞれ「2014/01/01」「2014/01/31」と入れてみました。
予想通り、週数も切り捨てされています。

開始日、終了日をそれぞれ「2014/01/01」「2014/12/31」と入れてみました。 ここでハタと、疑問がよぎりますね。月数と年数はこれでいいのか?と。しかし「片端入れ」では、確かにこのようになります。

開始日、終了日をそれぞれ「2014/01/01」「2014/12/31」と入れてみました。
ここでハタと、疑問がよぎりますね。月数と年数はこれでいいのか?と。しかし「片端入れ」では、確かにこのようになります。

ところがです。試しに「2014/01/02」「2015/01/01」としてみました。 するとどうしたことでしょう?日数は364日と変わらないにもかかわらず、月数と年数がひとつづつ増えていますね。これも何かおかしいような気もしますが「片端入れ」では、やはりこのようになるのです。理論的には正しくても、何だかしっくり来ないですよね。

ところがです。試しに「2014/01/02」「2015/01/01」としてみました。
するとどうしたことでしょう?日数は364日と変わらないにもかかわらず、月数と年数がひとつづつ増えていますね。これも何かおかしいような気もしますが「片端入れ」では、やはりこのようになるのです。理論的には正しくても、何だかしっくり来ないですよね。

そこで、これを「両端入れ」になるように、次のような式にしてみました。

日数=DateDiff(“d”,[開始日],[終了日])+1

週数=DateDiff(“w”,[開始日],[終了日])+1

月数=DateDiff(“m”,[開始日],[終了日])+1

年数=DateDiff(“yyyy”,[開始日],[終了日])+1

「2014/01/01」「2014/01/07」と入れてみました。 「両端入れ」ではこのようになります。

「2014/01/01」「2014/01/07」と入れてみました。
「両端入れ」ではこのようになります。

「2014/01/01」「2014/01/31」と入れてみました。 「両端入れ」ではこのようになります。

「2014/01/01」「2014/01/31」と入れてみました。
「両端入れ」ではこのようになります。

「2014/01/01」「2014/12/31」と入れてみました。 「両端入れ」ではこのようになります。

「2014/01/01」「2014/12/31」と入れてみました。
「両端入れ」ではこのようになります。

さて、それでは「2014/01/02」「2015/01/01」としてみました。 これも何だか変なような気がしますが「両端入れ」のルールには適っています。 つまりこれは、日本語の「足掛け」という数え方にあたります。

さて、それでは「2014/01/02」「2015/01/01」としてみました。
これも何だか変なような気がしますが「両端入れ」のルールには適っています。
つまりこれは、日本語の「足掛け」という数え方にあたります。

日数が一年以内でも月数や年数はこのようになるのです。ここで疑問に思うのは、月数と年数です。つまり、週が7日であるのは普遍的です。しかし、月数は30日である場合と、31に日である場合がありますね。更に2月は28日の場合と、4年に一度29日の場合があるわけです。同様に一年間の日数も4年に一度366日になります。一体どの日数を使って計算しているのでしょうか?
皆さんもうお分かりですね。Accessは、まさにそのとき時の「実際の日数」を元にしているのです。PC上では199/01/01以降、未来永劫に渡るすべての日付に一意的なシリアル値が当てられています。Accessは、そのシリアル値を即座に読み取って、左のような計算を実行しているわけです。

サンプルファイルはこちらからダウンロードすることが出来ます。

NO IMAGE