データベースでレコードを取り扱う上で避けては通れない「NULL」とは一体なんなのか、どのような特徴や制約があるのかについて解説したいと思います。
NULLとは
NULLは、ヌルやナルと読み、値が何も存在しない状態を表しています。値が存在しない状態とは、文字列の空文字(”)や数値の0などとは明確に区別されます。どちらかと言うと、NULLは特殊な値として扱われます。
基本的には、レコードを作成する時に値を何も指定しなかった列はNULL(何も指定していないから値が存在しない状態)となります。空文字や数値の0は、それぞれ明示的に値をセットしていることになります。
例えば以下のようなクエリ結果を見てみると、社員番号が00008の給料はNULLですが、社員番号が00007の部署コードは空文字であり、NULLではありません。
このNULL値を検索したい場合は、WHERE句の書き方を工夫しなければなりません。
SELECT * FROM Table_Syain WHERE 給料 = NULL ------------------------------------------------------------------------ 社員番号 名前 年齢 性別 生年月日 給料 部署コード ----- -------------------- ----------- ---- ---------- ----------- ----- (0 行処理されました)
このように、NULLを普通に検索してもヒットしません。前述した通りNULLは特殊な値になりますので、NULLであるレコードを検索するにはWHERE句に「項目名 IS NULL」と書かなければなりません。逆にNULLではないレコードを検索するには「項目名 IS NOT NULL」と書きます。
SELECT * FROM Table_Syain WHERE 給料 IS NULL ------------------------------------------------------------------------ 社員番号 名前 年齢 性別 生年月日 給料 部署コード ----- -------------------- ----------- ---- ---------- ----------- ----- 00008 増田 八助 30 男 1982-10-05 NULL B001 (1 行処理されました)
SELECT * FROM Table_Syain WHERE 給料 IS NOT NULL ------------------------------------------------------------------------ 社員番号 名前 年齢 性別 生年月日 給料 部署コード ----- -------------------- ----------- ---- ---------- ----------- ----- 00001 田中 一郎 20 男 1993-01-01 205000 A001 00002 山田 二郎 41 男 1972-01-02 420000 A001 00003 鈴木 三つ子 28 女 1985-01-03 250000 A004 00004 高橋 四郎 35 男 1978-01-04 360000 A005 00005 松村 五郎 26 男 1987-01-05 230000 A004 00006 前田 六実 20 女 1993-01-06 180000 A002 00007 七道 剛 28 男 1985-02-04 270000 (7 行処理されました)
それぞれ、WHERE句の指定を変えることで正しくレコードが取得できていることが分かります。
また、IN句にNULLを指定することはできません。
ちょっと例が悪いですが、給料がNULLのレコードが取得できていません。この例でNULL値も取得したい場合は、OR でIS NULL を繋げてあげると、NULLのレコードも取得できます。
NULLの使い道
NULLの使い道は、前述したとおり「値が存在しない状態を表す」ことにあります。文字列の場合、空文字はれっきとした値が存在しますし、数値の場合も0は明確に値が存在します。そこで例えば、外部のシステムが出力したCSVなんかをデータベースに取り込む際、値がセットされていない項目はNULLにすることで、処理の結果を分岐したい場合など、でしょうか。
日付の値は、取り扱うプログラムや環境によって初期値となる値が変わります(1900年1月1日とか)ので、文字列の空文字や数値の0のような表現がしづらいです。そこで、NULLを使うことで日付の値として何も存在しない(値がセットされていない)状況が簡単に作り出せるのです。
他には、テーブルの外部結合を行った結果、結合されるレコードが存在しない場合もNULLになります。
NULLを許容するかどうか
レコードの値としてNULL値を許容するかどうかを指定することができます。指定するには、テーブル定義から項目に対して指定します。現在の設定状況は、Management Studioの「テーブル」→「列」を開くことで分かります。
個人的には、極力文字列型や数値型はNULLを許容しない方が好きです。日付型だけは初期値の扱いが面倒なのでNULL許容してもいいと思います。
NULLが許容されると、一つ一つ後述するISNULL関数を使わなければならなくなったりと、NULLを考慮しないといけなくなるので面倒です。
NULLの演算
NULL値に対して、* や / 等の各種演算を行った場合、計算できないので結果はNULLになります。
また、集計関数を使用した時はNULLのレコードは無視されます。以下のような給料の平均値を求めるSQLを実行した場合を見てみると、社員は合計8人いるのに7で割られていることが分かります。
他にも、SUM MAX MIN でも同様にNULLのレコードは無視されます。COUNTの場合は少し特殊で、COUNT(*)はNULLも含めるがCOUNT(給料)はNULLを無視します。
ISNULL関数
NULL値をNULLのまま取り扱うのは、多少面倒です。上述のとおり、NULL値との演算は全てNULLになってしまいますが、例えば集計等を行った場合、値が無ければ0として取り扱いたいことが多いと思います。
そんな時は「ISNULL()」関数を使い、もし値がNULLだった場合に別の値に置き換えることができます。
ISNULL(変換対象の項目, 変換後の値)
さきほどのAVGでも、このISNULL()関数は有効です。ISNULL()した結果をAVGすれば、NULLではない値を集計していることになるのでカウントしてくれます。
NULL許容していて、このISNULL()をし忘れるとバグります。。。NULL許容していなかったら絶対にNULLは存在しない状態にデータベースレベルで実現できるので(開発者が何もしなくても)、余計な考慮をしなくて済むというお話です。
以上が、データベースにおけるNULLの取り扱いの説明です。
貴殿がウェブ上で公開されている「SQLServer2008虎の巻」が
とても分かりやすく、弊社の新人等への教育に活用させていただきたく。
具体には、以下のとおり使用したいと考えております。
「SQLServer2008虎の巻」内の初級編のページを人数分(20名程度)印刷し、
弊社社員が講師として説明を行う。
この様な利用方法の場合に関して、以下をご教示ください。
1.このような利用方法について許諾いただけますでしょうか?
以下、許諾いただける場合にご回答ください。
2.著作権料・利用料など何らかの費用支払いは必要でしょうか?
3.当該ページを印刷すると無用の広告の類が表示されてしまうため、
広告表示など無い状態の原稿をご提供いただけないでしょうか?
4.その他付帯事項、制約事項などありましたらご教示ください。