Null と空文字列

tabledesign
テーブルのデザインで,テキスト型フィールドのプロパティとして「値要求」と「空文字列の許可」がある。デフォルトでは「値要求」は「いいえ」,「空文字列の許可」は「はい」になっている。ということは,当該フィールドは

  1. 値を入れない(Null)
  2. 空文字列("")
  3. 何らかの文字列("なんらかのもじれつ")

という3種類の値をとる可能性があることになる。

Null と空文字列はどう違うのだろうか。

tabledatasheet
たとえば,テーブル [昼めし] には日付/時刻型フィールド [日付] とテキスト型フィールド [メニュー] があり,毎日その日の日付と食ったものを記録するものとする。8月1日はひばり食堂で山菜うどんと竹輪の磯辺揚げを食べた,そこで日付が 2005/08/01 のレコードにはメニューとして "山菜うどんと竹輪の磯辺揚げ" という値を入力する。

2日は何かを食べたのだが,何を食べたか忘れてしまったので,とりあえず空欄にしておき,後で思い出したときに入力することにした。3日は顔なじみのインド料理店で3種類のカレーとナンのランチセットだった。4日は何も食べなかった(昼めしヌキだった)。

さて,このように入力されたデータを基に,「8月中に昼めしヌキだった日数は何日あったか?」という集計を行いたいとしよう。クエリーをデザインし,[メニュー] の抽出条件に Is Null と書けば,メニューの値が Null であるレコードを抽出することができる。・・ところがその中には,「何を食べたか忘れてしまったので,とりあえず空欄にしておいた」2日が含まれてしまう! 2日はあくまでも「とりあえず空欄にしておいた」に過ぎないのであって,決して「昼めしヌキ」ではないのにもかかわらず。

このような事態を回避するにはどうしたらよいのか? ひとつの方法は,何を食べたか忘れてしまった日は空欄にするのではなく "不明" とでも入力しておくことである。だが本当に「不明」という名称の料理があったらどうするのか?(#ねえよ・・)

そこで,こうする。・・2日のメニューには「未入力」という意味で Null を入力(実際には,何も入力しなければ Null となる)し,4日の方には「何もないものを食べた」という意味で空文字列を入力するのだ。明示的に空文字列を入力するには ""(連続したダブルクォーテーション2個)とすればよい。そして,「8月中に昼めしヌキだった日数は何日あったか?」という集計を行うクエリーでは,[メニュー] の抽出条件に "" と書く。それはメニューの値が空文字列であるレコードを抽出し,Null であるレコードは対象にしない。

このように,「未入力である状態」と「あえて空白を入力した状態」とを区別したいとき,Null と空文字列を使い分けて対応することができる。

しかし,Null と空文字列は,一見して見分けがつかない。見た目ではどちらも空白である。にもかかわらず,抽出条件で Is Null とした時は Null だけが,"" とした時には空文字列だけがマッチする。これは混乱の元であり,意識していないとバグにもなる。

というわけで,ことりは原則として空文字列を使用しないようにしている。すなわち,テーブルをデザインする時,テキスト型フィールドの「空文字列の許可」は「いいえ」にする。そうすれば,空欄に見えるものは必ず Null であり,空文字列は存在しないから,すっきりする。

tabledatasheet2
では,何か食べたのだが何を食べたか忘れてしまった8月2日と,本当に何も食べなかった8月4日を,どう区別すればいいのか? ・・それには別にもう一つ,「食べたか食べなかったか」を記録する Yes/No型のフィールドを設ければよいのだ。

(記事の内容は Microsoft Access 2003 SP1 で確認しています)

| | コメント (2) | トラックバック (0)