VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
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.WHERE clauses. This means rows with NULL in a filtered column are silently excluded.
IS NULL explicitly:
Testing for NULL
Always useIS NULL and IS NOT NULL, never = NULL or != NULL:
<=> (the NULL-safe equality operator), which treats two NULLs as equal:
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
UseCOALESCE 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. AWHERE col IS NULL query can use an index on col. However:
NULLvalues are not considered equal in aUNIQUEindex — 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:
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
- MySQL JOINs Explained — how NULL propagates through LEFT JOIN results
- CHECK Constraints in MySQL — enforcing NOT NULL and other column rules

