データベース・プログラミング入門へ戻る  

 RDBの表

 実のところ、私はとある階層型データベースの使い手である。リレーショナル・データベース(RDB)に比べて、階層型のほうが人間の思考に合っており、XML等との相性も良い、と考えている。しかし、多勢に無勢、RDBにあらざればDBにあらず、といった昨今の風潮ではいたし方がない。データベースの本体、テーブルと呼ばれるものは以下のような二次元の表だ、として解説を進めることにする。

● テーブル

 リレーショナル・データベース(RDB)の本体は、今でこそテーブル(表)と言う名が一般的である。以下のようなものである。

KAIIN
SID NAMAE GEN DOB SYOKU
E02001 鈴木 ふみ F 1920/02/29 SY001
E02002 山田 一郎 M 1958/07/07 SY021
E02003 田中 健二 M 1942/10/15 SY022
E02004 伊藤 幸子 F 1968/03/10 SY001

 データベースの各テーブルには名前が付いている。この例では、KAIINである。
 第一行は、各欄の名称である。RDBでは欄はフィールドと呼ばれる。SIDは一連番号の欄、NAMAEは名前の欄、などである。
 第二行以降が表の中身で、一行が一組のデータ、つまりレコードである。たとえば、鈴木さんは女性で誕生日は1920年2月29日、一連番号はE02001、職業は別の表のSYOKU欄がSY001の行を参照、ということを表している。

 一連番号は、もちろん、数字でも良いが、上のテーブルのように文字列にしておくと融通が利くと思う。
 フィールドの名称は短めの英数字にしておくと、プログラムが書きやすく、読みやすくなる。「-」などの記号は使わないほうが無難である。別項で述べる問い合わせ言語SQLのキーワードは使えない。DATEなどの、ありふれた英語が予約されていて使えないので注意が必要である。

 なお、以下で「表」という場合は、テーブルを指す場合と、テーブルから導出され、テーブルのような外観を持つものの2通りがある。

● データ型

 SQLで使用できるデータの型はたくさんあるが、文字列、数値、日付の三種でたいていの用は足りる。型はテーブルを作成する際に指定する必要がある。後で変更するのは大変なので、設計時によく考えないといけない。
 文字列は、最大文字数を指定する。コード番号のように決まった長さのものは、その長さを採用すればよい。名前などは適当に50文字などと決めればよい。最大の長さは250文字程度のデータベースが多いようである。最近は数千から数万文字まで1フィールドに入れられるものもある。
 数値は、小数点以下のない整数と、小数点以下が許される実数の区別がある。32bitの符号付整数でたいていの場合はOKであろう。
 上述の表だと、以下のようになる。

SID   文字列(6文字)
NAMAE   文字列(50文字)
GEN   文字列(1文字)
DOB   日付
SYOKU   文字列(5文字)

● 1つのフィールドに複数のデータがある場合

 所属する委員会、のように、全く委員会に関わりのない人もいれば、複数の委員会に所属している人もいる、というフィールドには、区切り文字を使用すればよい。たとえば、一つの委員会なら、
  II003
 などであり、複数なら、
  II002;II028;II049
 などとする。所属する委員会がなければ、空文字列(長さ0の文字列)である。
 「; (セミコロン)」がこの場合の区切り文字である。
 JAVA言語などには、このような区切り文字のある文字列を扱う関数が用意されている。
 簡単な工夫だが、このような表現(トークン)に対しては、なぜかRDB推進者の歯切れは悪い。

● RDBに重複行は許されない

 RDBのレコードの内容は重複してはならない。RDBの理論的根拠が数学の「集合」だからである(ベン図上では同一点になってしまう)。
 筋から言えば、重複したデータが入力されたら自動的に一行にまとめられるべきである。しかし、現実のRDBは必ずしもそうなっていない。以前のデータは積極的に消さないといけない。
 そこで、オートインクリメント整数などといった、訳の分からないフィールドが登場することとなる。システムによっては、自動的に設定されてしまう。このような元来がつじつま合わせのためのフィールドは、プログラムからは使わないほうが良いだろう。

● インデックスの利用

 「集合」の観点からは、RDBのレコードには順番が付けられないはずである。無論、計算機内では何らかの順番に並んでいるはずであるが、その順は役に立たない。
 通常、人間が何かを整理するときは順に並べる。順に並んでいるとデータが取り出しやすいのは計算機も同じである。残念なことに、RDBは理論的にはこの要請に応えられない。
 そこで、インデックスが登場する。
 上述のKAIINテーブルだと、SIDは他の表からの参照の際、レコードの特定に利用される(キーになる)であろうから、インデックスを付けておく。名前は検索されるかもしれないから(逆引き)、インデックスを付けてもよい。インデックスを付けると付けないでは、処理速度に極端な差が出るはずである。インデックスは後から付けることもできるが、システム設計の観点からは、最初から付けておきたい。

● リレーションは設けない!

 RDBだからというのであろうか、複数のテーブルのフィールドを関連付けて表を連結する「リレーション」という機能が用意されていることが多い。しかし私の経験上、リレーションは利用しないほうがよい。
 まず、フィールドが自由に消せなくなる。リレーションにしたがって順番に消さないといけないのだ。ご迷惑機能と言うほかはない。また、多対多リレーションはなぜか直接設けることができない。これはRDBの理論的欠陥と思う。さらに、SQLを使うのなら、リレーションは不要である。

● 表の操作

 集合演算やデカルト積、関係演算(選択、射影、結合、商)などの表の操作は、RDBを使う以上、教養として知っておくほうが良い。SQLのSELECT文は、主に選択、射影、結合をするための操作である。
 通常、表の操作の結果は表である。テーブルにSELECT文を施した結果(クエリー)は、表の扱いになる。クエリーの表のデータを変更した場合に元のテーブルのデータが意図どおりに変更されるか否かの保証はない。レコードの削除や挿入はテーブルに対して直接行うのが無難である。

● カーソル

 個々のレコードをプログラムで扱うために、カーソルがある。通常は、SQLの問い合わせで得られた表の一行目をカーソルが指しているので、データをチェックしながらレコードを処理し、カーソルを一つずつ進めてゆく。
 上のテーブルの職業欄など、時にはさらに他のテーブルを参照する必要がある。中間結果の保持が必要なわけだが、このような場合はクエリー等で無理するのではなく、Visual BASICの配列などの、プログラミング言語の変数を利用すると良い。
 プログラム言語の配列が、ローカルな表、というわけだ。このローカルな表はもちろん共有されない。しかし、小回りは効く。

2002年11月6日 岡田好一