Null

Nullは、何もない、という意味で、プログラミング言語などコンピュータ関係では、「何も示さないもの」を表すのに使われる。同様のものとして、nil が使われることもある。ただし、PythonはNoneが使われる。

ドイツ語において Null}} は数値の0を意味し、発音は nʊl}} である。一方、英語において null}} は nʌl}} と発音される。ドイツ語においても、数値の0と区別するために、本記事の意味の Null}} は英語風に nʌl}} と発音される場合がある。

日本においては「ヌル」という発音が定着しているが、英語読みに近い「ナル」という発音で呼ばれる場合もある。例えば、JISのXのP4には「ナル値 」、XのP4には「ナル文字 」という記述がある。この他にも専門書や国家試験でも見られる。

プログラミング言語などにおいて、nullやnilといった予約語や定数名のものなどの意味がどういったものかは言語により、場合によっては実装ごとに違う。ポインタや参照のある言語では、ヌルポインタなどと呼ばれる何も指さない特別なポインタであることもあるし、Pythonのようにオブジェクトのひとつであることもある。古典的なLISPのように真理値の偽や空リスト「」を兼ねたものだったりすることもある。

1. 語源
-----

ラテン語で「無」を意味する nullus}}に由来する。nil もラテン語の nihil}} の短縮形に由来する。

英語では null}} はコンピュータに限らず使われ、しばしば zero}} または empty}} と交換可能である。例えば、null matrix}} は zero matrix}}、null set}} は empty set}}と同義である。

2. ヌルポインタ
---------

ポインタや参照が無効であることを示す。C言語では無効ポインタを表現するための特別な値として、処理系定義のNULLマクロが用意された。Cの規格ではNULLポインタの内部数値は0とは規定されていないが、代表的な実装では以下のようになっている。

define NULL    0)<WtXmlEndTag /> またC言語から派生したC++では、C言語から引き継いだNULLマクロ定義が存在するが、Cとは違ってvoid*から他の型へのポインタに暗黙変換することを禁止したため、C++03規格までは以下のように整定数0に等しかった。

define NULL   0<WtXmlEndTag /> しかし、これは基本整数型intの0と型システムの上では同じになるため、しばしばオーバーロードの呼び間違いが生じることとなった。これを解消するためC++11規格では専用のstd::nullptr_t型を持つリテラルを表すnullptrキーワードが導入され、NULLマクロは処理系定義となった。

C++以後の言語ではnullを最初から専用構文として導入した事例が多い。

3. その他のヌル
---------

PythonではNoneという名前で、その値は組込みオブジェクトである。バージョン2.4からNoneには代入できなくなった。Rubyではnilというキーワードで、意味は組込みオブジェクトである。LISPではNILで、どれでも同じようなものだが実体の詳細は様々で、carやcdrをとるとそれぞれでまたnilが返ってくる実装もあればエラーになる実装もある。

4. null型
--------

構文上、nullは多くの言語で特別なnullリテラルという扱いだが、リテラルのための型「null型」が規定される言語が存在する。null型の値はnullのみが許される。

プログラム言語の文法上null型が存在するケースでは、一般的な型同様にnull型を用いることが出来るが、null型を扱えない言語も存在する。

例えばJavaでは「null型」はあるが、ユーザーコードで利用することはできない。言語仕様では、nullリテラルはnull型であり、null型には名前がなく、null型の変数宣言やnull型へのキャストをすることは不可能である、という扱いとなっている。以上より、null型は内部的に存在するが、構文などの上でそれを扱うことができず、その値を表すリテラルのみが存在する。

5. ヌル文字
-------

6. ヌル文字列
--------

7. nullデバイス
-----------

nullデバイスは、存在しない架空のデバイスを表す。nullデバイスに出力すると、実際はどこにも出力されず廃棄される。

UNIXやLinuxでは/dev/null、MS-DOSやMS WindowsではNULで表される。

8. データベースのNULL
--------------

データベースのNULLは、欄が空欄であることを示す。これは人が読む用の表のNAにあたり、C言語のNULLよりは浮動小数点演算のNaNに近い。

具体的にはNULLには、未知・不明  の場合と適用不能・非存在  の場合がある。例えば、名前がNULLの場合、未知のNULLは「名前はあるが分からない」ということを、適用不能のNULLは「名前が存在しない」ことを示す。これはエドガー・F・コッドによる分類だが、彼はさらに詳細な分類をしている。

なおそれらに対し、名前欄が空文字列の場合は、名前はあり、知っていて、欄に書かれている通り「」であることを示す。未知や適用不能のために、空文字列、文字列 'UNKNOWN'、0、-1、9999年12月31日、未使用のコードなど特定のありえない値を例外値として使うことがしばしばあるが、それらは実際の値であるとして処理されてしまう危険がある。

NULLはNULL値と呼ばれることもあるが、コッドによると値ではない。値ではないので型もない。整数型の列にあるNULLも文字列型の列にあるNULLも同じNULLであり、NULL整数・NULL文字列などの区別はない。内部的にはNULLは、特定のビット列ではなく、値とは別個の「NULLかどうか」を表すメモリ領域で管理されていることが多い。

8.1. SQLのNULL
-------------

8.1.1. NULL を含む演算の結果
--------------------

NULLを含む演算の多くは結果がNULLとなる。例えば NULL + 1 NULL / 0 NOT NULL NULL AND TRUE LENGTH はいずれもNULLである。これは浮動小数点演算でNaNを含む式の結果がNaNになるのと似た規定である。この規定によりNULLを許容する演算は煩雑になりやすくなることから、データーベース・ベンダーによる拡張が行われている場合がある。この問題は、WHERE句でNULLでありうる列を診断しようとしたとき、特にDELETEやUPDATEで悲惨な結果を呼ぶことがある。回避方法は、NULLが混入する可能性を充分に検討し、IS NULL 演算子を駆使して式を慎重に組み立てる以外にない。

ただし少なからず場合に、NULLを含む演算で結果がNULL以外になる。このためNULLは無制限には伝播しない。ただししばしば、NULLの絡んだ演算の実装は不完全で、処理系依存が多い。

比較・IN述語など論理値を返すべき場面では、NULLを含む結果は UNKNOWN となる。UNKNOWN は、値ではないNULLとは異なり TRUE・FALSEに並ぶ第3の論理値である。例えば NULL = NULL NULL <> NULL NULL = 1 NULL <> 1 NULL < 1 NULL IN  NULL IN  などはいずれもUNKNOWNになる。ただし、UNKNOWNの扱いにもNULLに似た難しさがある。

論理式でNULLとならない場合がある。 NULL AND FALSE NULL OR TRUE はそれぞれFALSE、TRUEである。

Oracleは空文字列とNULLを区別しないため、NULL あるいは空文字列を含む演算で非標準な結果となることがある。例えば、文字列と NULL を連結すると本来は NULL になるが、Oracleでは文字列の値を変えない。

'A' || NULL   -- IS NULL, ただし Oracle では = 'A' NULL || NULL   -- IS NULL

8.1.2. NULLを扱うための工夫
-------------------

テーブルの各列には、NULLを保持できないと指定することができる。例えば、全ての行で必ず異なる値が含まれなければならないと指定されている列であっても、複数の行がNULLを保持できてしまう。そこで、この列にNULLを保持できないと指定すればこの問題が回避できる。

ソートでは、NULLはいかなる値よりも小さいとして扱われる。しかし論理値でのソートが実装されていれば、以下のように IS  NULL を第1のソートキーに使ってNULLを先または後に変更できる。 ORDER BY col IS NOT NULL, col   -- NULLは最初 ORDER BY col IS NULL, col     -- NULLは最後 また、CASE式やCOALESCE関数を使って、NULLに任意の値を割り当ててソートすることができる。以下の句はいずれも、colがNULLならば0を割り当ててソートする。 ORDER BY CASE WHEN col IS NULL THEN 0 ELSE col END ORDER BY COALESCE ORDER BY NVL   -- Oracleのみ

9. 脚注
-----