INTER-Mediator Lab. - Room 1
住所録では名前や電話番号を記録するだけでなく、「友人」「会社関連」などといった分類を入力したいと思うかもしれません。通常、そうした情報を文字列で入れていても役に立つ場合がありますが、常に一定の情報を入れないと意味がない場合もあります。たとえば、売り上げを記録するのに同じ商品であれば、すべて同じ商品名である必要があります。そうしないと、商品ごとの集計が簡単にはできなくなります。
このように、常に決まっているデータを入力したい場合、その決まったデータを単独のテーブルに入力し、そのテーブルの情報を参照して入力をします。こうした決まったデータを入れておくテーブルを「マスターテーブル」と一般には呼ばれています。
住所録をaddressテーブルで作っているとして、分類を記録するconnectionテーブルがデータベースに用意されているとします。idとcnameの2つのフィールドがあり、idフィールドが主キーフィールドです。
| id | cname |
|---|---|
| 1 | 親戚 |
| 2 | 友人 |
| 3 | 会社関係 |
ここで、住所録の各レコードで、種類を記録したいとします。そのような場合、以下のように、addressテーブルに、con_idフィールドを設けて、connectionテーブルのidフィールドと対応づけます。つまり、風下寒子さんは、「会社関係」の友人であることが記録されたわけです。
| id | pname | tel | con_id |
|---|---|---|---|
| 1 | 山田一郎 | 0123-456-9876 | 1 |
| 2 | 風下寒子 | 0123-456-9876 | 3 |
| 3 | 屋根裏夫 | 0123-456-9876 | 1 |
このような、数字で突き合わせて2つのテーブルの値を合成するのは、一見すると分かりにくく、余分なことをしていると思うかもしれません。con_idというフィールドに直接「会社関係」と入力した方が手っ取り早いと思うかもしれません。
上記のページを実際に作ったサンプルは、「実験環境(別ウインドウに表示)」に用意してあります。実験環境のページのsample7.html/phpをご覧ください。
まず、この方法の利点を説明しましょう。住所録にたくさんのデータが蓄積された後、「親戚」ではなくて「親類」に変更したいとします。上記のようなデータ構造を取っていれば、connectionフィールドのid=1のレコードのcnameフィールドを変更するだけですべて変更が完了します。addressフィールドのいくつかのレコードのあるフィールドに「親戚」という文字列が入っていたら、それらを検索して特定して、不定数のレコードに対する更新を正しく行う必要があり、より多くの作業が発生することになります。このように、表現や情報そのものを別途管理するということで、確実に同一の値を記録管理できるということです。
このような複数のテーブルでデータを管理して突き合わせなどを行う仕組みを持っているのがリレーショナルデータベースの特徴です。マスターテーブルを使う手法はその代表的な利用方法です。
この住所録が、顧客管理的なものだったとします。そして、各顧客に対するコンタクト(訪問、問い合わせ、電話連絡といったもの)を記録したい場合、addressテーブル以外に、コンタクトをいつ誰がどのような方法で行い、どうだったのかを記録するcontactテーブルを作ります。このとき、1人の顧客に対しては複数のコンタクト結果が発生することが想定されます。一方、1回のコンタクトは1顧客だけという運用をします。このような場合、顧客とコンタクトの関係は「1対多」と呼ばれます。contactテーブルには、対応するaddressテーブルのid値を入れるフィールド(たとえば、address_idフィールド)を用意して、そこに対応するレコードのidフィールドの値を入力します。逆に、addressフィールドには対応するcontactテーブルの主キー値を記録するフィールドは設けません。2つ以上かもしれないという数が決まらない問題もさることながら、contactテーブルのaddress_idフィールドの値から組み合わせは特定できることから、それ以上の対応付けのための情報は不要になります。
なお、ここで、マスターテーブルの値をコピーした方がいいような場合もあります。売り上げをテーブルで記録する場合、商品を別のテーブルで管理するという商品マスターを確保するのは典型的な設計手法です。商品マスター側では、商品名や単価を記録します。売り上げのテーブルでは、商品テーブルの特定のレコードを参照する情報をだけを記録するということができます。商品名や単価は売り上げのテーブルでは記録しないというわけです。
しかしながら、そうなると、あるときある商品の単価が変わった場合、不都合が起きるかもしれません。商品マスターの単価を書き換えれば、過去の売り上げデータはすべて新しい単価で売ったという結果になります。このように、変更があるような情報については、商品マスターの単価の値を、売り上げのテーブルにもつどつどコピーして記録するのが一般的です。それでも「現在の単価」を記録する意味で商品テーブルを別に用意するのは、間違いなく入力できるなどのメリットをもたらすものです。
addressテーブルのcon_idフィールドに入力するためにポップアップメニューを利用したいとします。このとき、addressテーブルのためのコンテキストだけではなく、connectionテーブルのためのコンテキストも必要になります。定義ファイルでは複数のコンテキストを定義でき、それらは並べて記述します。以下のように、区切りに線を入れて、2つのコンテキストが定義されていることを示します。なお、connectionコンテキストについてはkeyの指定はあってもなくてもかまいません。connectionテーブルにクライアントから更新をすることがないので、必要ないのです。
name: address
key: id
-
name: con
view: connection
そして、ページファイルでは次のようなターゲット指定を持った要素が加わります。
<table>
<thead>
<tr><th>名前</th><th>電話番号</th><th>分類</th></tr>
</thead>
<tbody>
<tr>
<td class="IM[address@pname]"></td>
<td class="IM[address@tel]"></td>
<td>
<select class="IM[address@con_id]">
<option class="IM[con@id@value|con@cname]"></option>
</select>
</td>
</tr>
</tbody>
</table>
これで、テーブルには3つ目の「分類」列が追加され、各レコードに対してポップアップメニューが表示されます。すでにconn_idフィールドにデータがあれば、それに対応する選択肢が選択されているはずです。また、ポップアップメニューを選択すれば、その選択結果で、conn_idの値が更新されます。
ページファイルのターゲット指定をあらためて解説をします。まず、addressコンテキストの展開中に、conという別のコンテキストが登場しています。ここでは、まず、TBODY/TRによるエンクロージャー/リピーターが識別されますが、そのとき、さらに内部にSELCT/OPTIONによるエンクロージャー/リピーターが存在しています。リピーター内部のエンクロージャー以下の要素は、データベースの結果を合成するときには特に何もしません。その代わり、データベースから得られたデータを合成した後、さらに内部のエンクロージャー/リピーターの展開に入ります。ここでは、名前と電話番号をTD要素の値に組み込んだ後、conというnameを持つコンテキストを見て、connectionテーブルへアクセスをしてレコードを受け取り、レコードの数だけOPTIONタグを複製して、OPTIONタグ要素内部にconnectionテーブルから得られた結果を合成します。
OPTIONタグ要素では、2つの新しい内容が含まれています。まず、ターゲット指定は、半角の|によって区切る事で1つの要素に複数の指定を入れる事ができ、それぞれの合成が行われます。ターゲット指定では@で区切られた3つ目の項目があります。3つ目の項目は、データベースのデータを設定する先を指定します。
この場合だと、「con@id@value」という指定により、conコンテキスト(connectionテーブル)のidフィールドの値を、OPTIONタグ要素のvalue属性の値にします。続いて「con@cname」により、conコンテキストのcnameフィールドの値がOPTIONタグの値として設定され、その文字列が選択肢として見るようになります。結果として、ポップアップメニュー部分はデータベースから得れた結果を合成すると、次のようなHTMLと同じ結果になります。
<select class="IM[address@conn_id]">
<option class="IM[con@id@value|con@cname]" value="1">親類</option>
<option class="IM[con@id@value|con@cname]" value="2" >友人</option>
<option class="IM[con@id@value|con@cname]" value="3" >会社関係</option>
</select>
ターゲット指定の3つ目の項目では、以下のような仕組みを利用できます。
読み終わったとき、以下のラジオボタンのいずれかを選択して、「読み終わった」ボタンをクリックしてください。
開いてから今まで、このページを、
このページの内容について、自分が感じる理解度は、
←クリックすると、次のページに移動します。