メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
MySQL の NULL は、ゼロでも空文字列でも false でもありません。不明を意味します。この区別は追跡しにくいバグを引き起こします。クエリはエラーなしで実行され、黙って誤った結果を返すからです。

NULL は値ではない

NULL は値の不在を表します。NULL を何かと比較しても、別の NULL との比較であっても、true も false も返りません。NULL が返ります。
デフォルトでは MySQL の sql_mode に PIPES_AS_CONCAT が含まれないため、|| は文字列の連結ではなく論理 OR です。'hello' || 'world' は 'helloworld' ではなく 0 に評価されます。これは PostgreSQL や ANSI 標準とは異なり、そちらでは || は常に連結です。MySQL で文字列を連結するには CONCAT() を使ってください。 これが三値論理です。true、false、そして不明 (NULL) です。NULL との比較はすべて不明を生み、MySQL は WHERE 句でこれを false として扱います。つまり、フィルタされる列に NULL を持つ行は黙って除外されます。
NULL の行を含めるには、IS NULL を明示的に使います。

NULL の判定

常に IS NULL と IS NOT NULL を使い、= NULL や != NULL は決して使わないでください。
MySQL には、2 つの NULL を等しいものとして扱う <=> (NULL 安全な等価演算子) もあります。
これは、NULL どうしを一致させたい WHERE 句、たとえば NULL になり得る 2 つの列を比較するクエリで役立ちます。

集計における NULL

集計関数 (COUNT、SUM、AVG など) は NULL 値を無視します。例外は COUNT(*) です。
COUNT(*) は 3 を返します。COUNT(referrer) は 2 を返します。NULL の行が除外されるためです。これは意図された動作ですが、COUNT(column) が COUNT(*) と等しいと期待する開発者を驚かせます。

式における NULL の処理

列が NULL のときにデフォルト値で置き換えるには、COALESCE を使います。
IFNULL(column, default) は、引数が 2 つの場合には同等です。
NULLIF(a, b) は a = b のときに NULL を返し、それ以外では a を返します。ゼロ除算を避けるのに役立ちます。
NULL は JOIN の動作にも分かりにくい形で影響します。LEFT JOIN は一致が存在しないとき右側の列に NULL を返し、その NULL 列を WHERE でフィルタすると、黙って INNER JOIN に変わります。サンプルデータベースを使って ON と WHERE の違いを順に追った MySQL の LEFT JOIN を参照してください。

NULL とインデックス

MySQL のインデックスは NULL 値を格納します。WHERE col IS NULL のクエリは col のインデックスを使えます。ただし次の点に注意してください。
  • UNIQUE インデックスでは NULL 値は等しいとみなされません。一意列は複数の NULL 値を含むことができます
  • 複合インデックスでは、どの列位置の NULL も通常どおりインデックスされます

よくある質問

省略可能なテキストフィールドには NULL と空文字列のどちらを使うべきですか?

本当に存在しないデータには NULL を優先してください。空文字列 ('') は「明示的に空に設定された」ことを意味し、「提供されていない」とは異なります。両者を混ぜると不整合が生じます。WHERE col IS NULL と WHERE col = '' は異なる条件です。1 つの規約を選び、一貫して適用してください。

なぜ NOT IN は NULL があると予期しない動作をするのですか?

NULL を 1 つでも返すサブクエリを伴う NOT IN は、常に空の結果セットを返します。
サブクエリが NULL を返す可能性があるときは、代わりに NOT EXISTS を使ってください。

ORDER BY は NULL をソートしますか?

はい。デフォルトでは、MySQL は昇順で NULL 値を最初に、降順で最後にソートします。MySQL は NULLS FIRST / NULLS LAST 構文をサポートしていません (それは PostgreSQL です)。NULL の位置を制御するには、ソート式を使います。
col IS NULL は非 NULL 値に対して 0、NULL に対して 1 に評価されるため、これで昇順にソートすると NULL が末尾に押しやられます。

トラブルシューティング

関連項目