VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
NULL は値ではない
NULL は値の不在を表します。NULL を何かと比較しても、別の NULL との比較であっても、true も false も返りません。NULL が返ります。sql_mode に PIPES_AS_CONCAT が含まれないため、|| は文字列の連結ではなく論理 OR です。'hello' || 'world' は 'helloworld' ではなく 0 に評価されます。これは PostgreSQL や ANSI 標準とは異なり、そちらでは || は常に連結です。MySQL で文字列を連結するには CONCAT() を使ってください。
これが三値論理です。true、false、そして不明 (NULL) です。NULL との比較はすべて不明を生み、MySQL は WHERE 句でこれを false として扱います。つまり、フィルタされる列に NULL を持つ行は黙って除外されます。
IS NULL を明示的に使います。
NULL の判定
常にIS NULL と IS NOT NULL を使い、= 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 は、常に空の結果セットを返します。
NOT EXISTS を使ってください。
ORDER BY は NULL をソートしますか?
はい。デフォルトでは、MySQL は昇順で NULL 値を最初に、降順で最後にソートします。MySQL は NULLS FIRST / NULLS LAST 構文をサポートしていません (それは PostgreSQL です)。NULL の位置を制御するには、ソート式を使います。
col IS NULL は非 NULL 値に対して 0、NULL に対して 1 に評価されるため、これで昇順にソートすると NULL が末尾に押しやられます。
トラブルシューティング
関連項目
- MySQL の JOIN のパフォーマンスとよくある間違い — 結合で NULL が引き起こす行数の誤りのバグ
- MySQL の CHECK 制約 — NOT NULL やその他の列ルールを強制する
- MySQL の本物のブール値 — ブール集計が NULL をどう扱うか
- MySQL の INNER JOIN — 内部結合が NULL を表示する代わりに行を落とす理由
- MySQL の演算子 — NULL との比較が NULL を返す理由
- MySQL の IS NULL — WHERE 句で欠けている値を判定する
- MySQL の LEFT JOIN — 外部結合の NULL がどこから来るか