Skip to main content

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

All examples in this guide work on VillageSQL. Install Now →
NULL in MySQL doesn’t mean zero, empty string, or false. It means unknown — and that distinction causes bugs that are hard to track down because the queries run without errors and return wrong results silently.

NULL Is Not a Value

NULL represents the absence of a value. Comparing NULL to anything — including another NULL — doesn’t return true or false. It returns NULL.
This is three-valued logic: true, false, and unknown (NULL). Any comparison with NULL produces unknown, which MySQL treats as false in WHERE clauses. This means rows with NULL in a filtered column are silently excluded.
To include NULL rows, use IS NULL explicitly:

Testing for NULL

Always use IS NULL and IS NOT NULL, never = NULL or != NULL:
MySQL also provides <=> (the NULL-safe equality operator), which treats two NULLs as equal:
This is useful in WHERE clauses when you want to match NULL-to-NULL, such as in queries comparing two potentially-null columns.

NULL in Aggregates

Aggregate functions (COUNT, SUM, AVG, etc.) ignore NULL values — except COUNT(*).
COUNT(*) returns 3. COUNT(referrer) returns 2 — the NULL row is excluded. This is intentional behavior, but it surprises developers who expect COUNT(column) to equal COUNT(*).

Handling NULL in Expressions

Use COALESCE to substitute a default value when a column is NULL:
IFNULL(column, default) is equivalent for the two-argument case:
NULLIF(a, b) returns NULL when a = b, otherwise returns a. Useful for avoiding division-by-zero:
NULL also affects JOIN behavior in non-obvious ways. A LEFT JOIN returns NULL for right-side columns when no match exists, and filtering on those NULL columns in WHERE silently converts it to an INNER JOIN. See MySQL JOINs Explained for the ON vs. WHERE distinction.

NULL and Indexes

MySQL indexes store NULL values. A WHERE col IS NULL query can use an index on col. However:
  • NULL values are not considered equal in a UNIQUE index — a unique column can contain multiple NULL values
  • In a composite index, NULL in any column position is indexed normally

Frequently Asked Questions

Should I use NULL or empty string for optional text fields?

Prefer NULL for genuinely absent data. Empty string ('') means “explicitly set to empty” and is distinct from “not provided.” Mixing them creates inconsistency — WHERE col IS NULL and WHERE col = '' are different conditions. Pick one convention and apply it consistently.

Why does NOT IN behave unexpectedly with NULLs?

NOT IN with a subquery that returns any NULL always returns an empty result set:
Use NOT EXISTS instead when the subquery might return NULLs:

Does ORDER BY sort NULLs?

Yes. By default, MySQL sorts NULL values first in ascending order and last in descending order. MySQL doesn’t support NULLS FIRST / NULLS LAST syntax (that’s PostgreSQL). To control NULL placement, use a sort expression:
col IS NULL evaluates to 0 for non-NULL values and 1 for NULL, so sorting by it ascending pushes NULLs to the end.

Troubleshooting

See also