閉じる

「NULL」とは何か?空文字や0との違いと落とし穴を理解する

プログラミングでよく見る「NULL」は、見慣れているのに理解があいまいになりがちな概念です。

空文字や0、falseと混同すると、思わぬバグに直結します。

本記事では、NULLの基礎から違い、典型的な落とし穴、安全に扱うための設計とコードのコツまでを、初心者向けに順を追って解説します。

NULLとは?基礎と考え方

NULLの意味と役割

「値が存在しない」を表す特別な印

NULLは「値が入っていない」ことを示すための特別な記号のようなものです。

変数やデータベースの列といった入れ物はあるのに、その中身がまだ決まっていない、わからない、そもそも適用できない場合に使われます。

NULLはデータの「欠如」を表し、値の一種ではありません

「ない」と「空」は違います

空文字や0は「存在するが空/ゼロ」という意味を持ちます。

一方でNULLは「そもそも値がない」ことを表します。

NULLは「空(長さ0や要素0)」とは別物であり、ここを取り違えるとロジックが崩れます。

歴史的な背景と役割の難しさ

NULLは柔軟さをもたらしましたが、同時に多くのバグの原因にもなりました。

NULLを提案したコンピュータ科学者トニー・ホーア氏は、後年これを「10億ドルの間違い」と呼びました。

便利だが危険、それがNULLの本質です。

値がないとは何か

未入力/不明/適用不可の3類型

「値がない」は大きく次の3つに分けられます。

未入力(まだ入れていない)、不明(わからない)、適用不可(その項目に意味がない)。

どの「ない」なのかを区別することが、設計と実装の品質を左右します

具体例でイメージする

人名のミドルネームは、存在しない人も多いです。

このとき、空文字(“”)は「意図的に空」と解釈され、NULLは「不明や未設定」を意味します。

気温の0は寒さを指す確かな値ですが、NULLは「未測定」です。

0とNULLは同じではありません

業務でよくある「まだ決まっていない」

注文の発送日時(shipped_at)がNULLなら「まだ発送していない」、日時が入れば「発送済み」です。

空文字にするより、NULLの方が自然に表現できます。

使われる場面

データベースの可任意な列

住所の「建物名」のように任意の項目ではNULLが使われます。

必須か任意かをスキーマで明示すると、後工程のバグを減らせます。

アプリやAPIのオプション値

設定ファイルやAPIレスポンスで、省略や未設定を表す際にNULLが登場します。

空と未設定を混同しないことが重要です。

一時的に未取得の値

キャッシュが未ロードの状態や、遅延取得の前段階でNULLを使うことがあります。

10億ドルの間違いとは

呼び名の由来

NULLの設計に関わったトニー・ホーア氏は、それがもたらした損失と苦労を振り返り、「10億ドルの間違い」と表現しました。

何が間違いを生むのか

NULL参照エラーや、NULLを想定しない比較・演算が、障害の大きな原因になります。

「どこにNULLが来るか」「来たらどうするか」を常に設計とコードで扱う必要があります

教訓

NULLは無くせないが、設計と型、演算子を活用して危険域を狭められます。

無警戒なNULLは事故の元です。

NULLと空文字・0・falseの違い

空文字(“”)との違い

意味の違い

空文字は文字列型の有効な値で、長さ0です。

NULLは文字列が「存在しない」状態です。

空文字は「あるけど空」、NULLは「そもそも無い」と覚えましょう。

振る舞いの違い(例: JavaScript)

JavaScript
const s1 = "";
const s2 = null;

console.log(s1.length); // 0
console.log(s2.length); // TypeError: Cannot read properties of null

空文字は長さを測れますが、NULLはプロパティ参照自体が失敗します。

データベースでの注意

多くのDBでは空文字とNULLは別物ですが、製品によって扱いが異なる場合があります。

DBごとの仕様を確認するのが安全です。

数値0との違い

意味の違い

0は数値の「量がゼロ」という確かな値です。

NULLは「数自体がない」状態です。

在庫0と在庫不明は別の意味です。

振る舞いの違い

  • JavaScriptでは型変換により思わぬ結果が出ます。
JavaScript
null + 1        // 1 (Number(null)が0になるため)
Number(null)    // 0
null == 0       // false

計算前にNULLを明示的に扱うことが大切です。

  • SQLではNULLが混ざると結果がNULLになる計算が多いです。
SQL
SELECT 1 + NULL;   -- 結果: NULL

ビジネスの例

価格が0円(無料)と、価格が未定(NULL)では意味が大きく違います。

ここを混同すると表示や請求で不具合が起きます。

falseとの違い

意味の違い

falseは「条件が成り立たない」という真偽の値です。

NULLは「真偽が不明」や「まだ決まっていない」を表せます。

条件分岐での落とし穴(JavaScript)

JavaScript
if (value) { /* 真 */ } else { /* 偽またはfalsy */ }

JavaScriptではNULLはfalsyでfalse扱いになりますが、falseとNULLは同一ではありません

利用規約に「未回答(NULL)」と「拒否(false)」が混ざると誤動作します。

空配列・空オブジェクトとの違い

容器が空と容器が存在しない

空配列([])や空オブジェクト({})は「容器はあるが中身がない」状態です。

NULLは「容器自体がない」状態です。

イテレーション可能かどうかに影響します。

例(JavaScript)

JavaScript
const list1 = [];
const list2 = null;

for (const x of list1) {}  // 何も回らないが安全
for (const x of list2) {}  // TypeError

必要に応じてデフォルトを使います。

JavaScript
const safe = (list2 ?? []);

undefinedやNaNとの違い

undefinedとnull

JavaScriptのundefinedは「未定義」、nullは「意図的な無」を表します。

両者は似ていますが別物です。

==では緩く等しいが、===では等しくない点に注意しましょう。

NaNは数値演算の失敗

NaNは「数値にならない」という演算結果を表す特殊な数値です。

NULLとは役割が違います。

JavaScript
Number("abc")    // NaN
NaN === NaN      // false
Number.isNaN(NaN) // true

まとめ表

意味OKな用途よくある落とし穴
null値が存在しない未入力/不明/適用不可任意項目、不明値プロパティ参照やメソッド呼び出しが失敗
“”長さ0の文字列入力は空だが意図的表示用の空、初期値NULLと取り違える
0数量がゼロ在庫0、温度0集計の初期値不明値と混同
false真偽の偽チェック未通過フラグ未回答(NULL)と混同
[]/{}空の容器要素0/プロパティ0ループ安全NULLと混在でエラー
undefined未定義(JS)変数未代入内部的な未定義nullと混同
NaN数値にできない0/0、無効変換演算の失敗表示比較に失敗する

「空」と「不在」の線引きを常に意識することが、安全なコードの第一歩です。

NULLの落とし穴とバグ

ヌル参照エラー

何が起きるのか

NULLに対してプロパティ参照やメソッド呼び出しを行うと、実行時エラーになります。

JavaScriptならTypeError、JavaならNullPointerExceptionです。

最も頻出するクラッシュ原因の1つです

JavaScript
const name = null;
name.toUpperCase(); // TypeError

比較の誤り

緩い比較の罠(JavaScript)

JavaScript
null == undefined  // true
null == 0          // false
null === undefined // false

===を基本に使うことで、意図しない型変換を防げます。

equals呼び出しの罠(Java系)

JavaScript
String s = null;
// s.equals("OK"); // NPE
"OK".equals(s);    // 安全

呼び出し側をリテラルにするなどで、NULL呼び出しを避けます。

メソッド呼び出しの失敗

チェーンでの崩壊

JavaScript
const user = null;
// user.profile.name  // TypeError

深いプロパティ参照は、どこか1つでもNULLだと崩れます。

途中のNULLを想定した書き方が必要です。

長さやプロパティ参照の失敗

lengthやキーの取得

JavaScript
const s = null;
// s.length       // TypeError
// Object.keys(null) // TypeError

処理前に「入れ物があるか」を確認しましょう。

SQLで= NULLは誤り

比較の正しい書き方

SQLではNULLは通常の比較演算子(=, <>)では比較できません。

JavaScript
-- 誤り
SELECT * FROM users WHERE middle_name = NULL;

-- 正しい
SELECT * FROM users WHERE middle_name IS NULL;
SELECT * FROM users WHERE middle_name IS NOT NULL;

集計や表示で値を埋めるときはCOALESCEを使います。

JavaScript
SELECT COALESCE(middle_name, '(なし)') AS middle_name FROM users;

SQLでは必ずIS NULL/IS NOT NULLを使うと覚えましょう。

NULLの安全な扱い方

NULLを設計で減らす

必須と任意を最初に決める

スキーマ設計で、必須はNOT NULL、任意はNULL許容と明記します。

「NULLが来ない世界」を増やすほどコードは安全になります

論理的に不要なNULLを作らない

意味のある初期値が定義できる場合、NULLにせず初期値で表現します。

ただし、0や空文字が本当に適切な意味かは必ず検討します。

初期値やデフォルトを決める

入力や表示の初期値

表示テキストなら””、リストなら[]、カウンタなら0など、用途に応じた初期値を選びます。

JavaScript
const items = [];           // ループ安全
const title = "";           // 表示の初期値
let count = 0;              // 集計の初期値

意図が伝わる初期値を選ぶと、後続処理が簡単になります。

SQLでの埋め込み

SQL
SELECT COALESCE(points, 0) AS points FROM users;

COALESCEでNULLを安全に置き換えられます。

早期returnでnullチェック

ガード節で見通しを良くする

ネストを深くするより、早めにNULLを弾いて返すと読みやすくなります。

JavaScript
function getUpper(name) {
  if (name == null) return "(未設定)";
  return name.toUpperCase();
}

最初にNULLを扱うと、その後のロジックが単純になります。

オプショナル型の活用

型で「NULLかもしれない」を表明する

TypeScriptのstring | null、Kotlin/SwiftのString?のように、型でNULL可能性を表します。

コンパイル時にチェックされるため、実行時エラーが減ります

JavaScript
function greet(name: string | null) {
  if (name === null) return "Hello, guest";
  return `Hello, ${name}`;
}

オプショナルチェイニング

中継点のNULLを安全に渡る

JavaScriptやTypeScript、Kotlinなどでは?.で安全に辿れます。

JavaScript
const url = user?.profile?.avatarUrl ?? "/placeholder.png";

存在すれば取得、無ければundefined/nullを返すため、チェーンが安全になります。

null合体演算子

NULL/undefinedのときだけ代替する

JavaScript
const shown = input ?? "N/A";  // inputがnull/undefinedのとき"N/A"

||と異なり、0や””を潰しません。

JavaScript
0 || 10   // 10 (意図せず上書き)
0 ?? 10   // 0  (期待通り保持)

「0や空文字を有効な値として扱う」なら??を使うのが安全です。

SQLはIS NULL/IS NOT NULLを使う

基本の型

比較はIS NULL/IS NOT NULL、置き換えはCOALESCEを使います。

これだけで多くのバグを避けられます。

SQL
WHERE deleted_at IS NULL
SELECT COALESCE(note, '(なし)') AS note

型でnull許容を明示する

宣言で意図を伝える

  • コード: TypeScriptでname: stringとname: string | nullを使い分ける
  • DB: NOT NULL制約とDEFAULT値で意図を固定する

「ここはNULLが来る/来ない」を型とスキーマで宣言すると、チーム全体で安全になります。

まとめ

NULLは「値が存在しない」ことを表す特別な概念で、空文字や0、falseとは意味も振る舞いも異なります。

空(あるが空)と不在(そもそも無い)を区別することが、正しい設計とバグ削減の鍵です。

よくある落とし穴は、プロパティ参照やメソッド呼び出しの失敗、緩い比較、SQLでの= NULLなどです。

対策として、必須/任意の明確化、適切な初期値、早期return、オプショナル型、オプショナルチェイニング、null合体演算子、SQLのIS NULL/COALESCEを活用しましょう。

NULLは「世紀の発明」でありながら「10億ドルの間違い」とも呼ばれます。

用法を正しく理解し、危険を封じる設計とコードを書くことが、安定したアプリへの最短ルートです。

この記事を書いた人
エーテリア編集部
エーテリア編集部

このサイトでは、プログラミングをこれから学びたい初心者の方に向けて記事を書いています。 基本的な用語や環境構築の手順から、実際に手を動かして学べるサンプルコードまで、わかりやすく整理することを心がけています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!