NULLの扱い | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

データベースにはNULL(つまり、値が存在しないことを表す値)を格納することができます。
しかしNULLをSQLで扱う場合、その癖を十分に理解していないと、誤った操作をしてしまったりします。

NULLの登録

まずはNULLをデータベースに登録する際の動きですが、NOT NULL制約、DEFAULT制約の設定されていないカラムに対してNULLをセットしてやればNULLが登録され、明示的に指定しなくとも勝手にNULLが登録されます。


いや、何もセットされないといった方が正しいでしょうか。

このへんは特に変わったことでもありません。


NULLと空文字、スペースとの違い
NULLと同じように値がないことを表すのに空文字('')やスペース(' ')を使うこともありますが、これはRDBMSによって動作に違いがあるので注意が必要です。
【Oracle】
Oracleの場合、主要なデータ型のカラムに対し、空文字、スペースを挿入すると実際には以下の表のような値が登録されます。

データ型 空文字 スペース
CHAR(固定長文字列) NULL 定義長分のスペース
VARCHAR2(可変長文字列) NULL スペース
NUMBER(数値) NULL エラー
DATE(日時) NULL エラー


Oracleには空文字という概念がないようです。

【SQL Server】
では、SQL Serverの場合はどうでしょう?


データ型 空文字 スペース
CHAR(固定長文字列) 空文字 空文字
VARCHAR(可変長文字列) 空文字 空文字
INT(数値) 0 0
DATETIME(日時) 1900/01/01 00:00:00 1900/01/01 00:00:00


空文字もスペースも空文字として扱われるようです。


NULLとは扱いが違うようです。


面白いのは、数値型や日時型に空文字をセットした時でしょうか。


Oracleのようにエラーにならないで勝手にそのデータ型の”値なし”を表す値になってしまいます。


気が利いてるんだか余計なおせっかいなんだかよくわかりません。



ただ、NULL、空文字、スペースを混同して使用すると誤った操作を誘発する可能性が高くなるのは間違いないでしょう。


データベース設計を行う際に、これらの特殊な値の使用方法についてルールを定めておくべきかと思います。

NULLの比較
WHERE句などでNULLとの比較を行う場合、"="、 "!="、">"、"<" "=>"、"<="、LIKE、INなどの演算子を使用しても何もヒットしません。
NULLは値がないことを表すため、比較対象にもならないということです。

では、こういうのはどうでしょう?

WHERE A = NULL OR A = 'ABC'

これもだめなんですね...

一見すると、たとえ左の条件が無効であっても、右の条件が有効だからヒットするんじゃないかと思えるのですが、左の条件を比較する時点ですべての行が比較対象外となってしまうので、結局何もヒットしないのです。

NULLとの比較を行える演算子は、IS NULL、IS NOT NULLの2つだけなのです。

上記の例はこのように直すと有効になります。

WHERE A IS NULL OR A = 'ABC'

では、ついでに空文字やスペースはどうでしょうか?

【Oracle】
結果
= ''何も返らない
= ' '' 'を持つ行が返る。

登録時と同じで、空文字はNULLと解釈されるようです。

つまり = NULLでは何も返りません。

スペースはそのままスペースと解釈されるようです。

【SQL Server】
結果
= '' ''を持つ行が返る
= ' ' ''を持つ行が返る。

これも登録時と同じで、空文字もスペースも空文字と解釈されるようです。
NULLの並べ替え
ORDER BY句でNULLを含む列での並べ替えを行うとどうなるのでしょうか?

【Oracle】
昇順に並べるとスペース、一般文字、NULLの順に並びます。降順だとその逆です。

【SQL Server】
Oracleと違って昇順に並べ替えるとNULL、空文字、一般文字の順に並びます。降順だとその逆です。


NULLのグルーピング
【Oracle、SQL Server】
グルーピングのキーとなるカラムがNULLの場合はNULLもグルーピングの対象となります。

集計カラムがNULLの場合はそのカラムは集計対象外となります。