Incorrect
WHERE MiddleName = NULL
Result: Always returns zero rows because the comparison evaluates to UNKNOWN.
In SQL, NULL is not a value; it is a marker indicating that a value is missing or unknown. This distinction is the source of many bugs and requires a fundamental shift in how you think about logic.
Most programming languages use Two-Valued Logic: a statement is either TRUE or FALSE.
SQL uses Three-Valued Logic:
TRUEFALSEUNKNOWNWhen you compare something to NULL, the result is always UNKNOWN.
In math, $x = x$ is always true. In SQL, NULL = NULL is NOT true. It is UNKNOWN.
Think of it this way:
Because NULL is unknown, you cannot use the standard equals operator (=) to find it.
Incorrect
WHERE MiddleName = NULL
Result: Always returns zero rows because the comparison evaluates to UNKNOWN.
Correct
WHERE MiddleName IS NULL
Result: Correcty identifies rows where the marker is present.
| Expression | Result |
|---|---|
TRUE AND UNKNOWN | UNKNOWN |
FALSE AND UNKNOWN | FALSE (Short-circuited!) |
TRUE OR UNKNOWN | TRUE (Short-circuited!) |
FALSE OR UNKNOWN | UNKNOWN |
NOT UNKNOWN | UNKNOWN |
We have a Profiles table:
| UserID | Username | PhoneNumber | |
|---|---|---|---|
| 1 | tech_guy | tg@example.com | 555-0101 |
| 2 | data_queen | dq@example.com | NULL |
| 3 | sql_pro | sp@example.com | 555-0202 |
| 4 | ghost | NULL | NULL |
SELECT UsernameFROM ProfilesWHERE PhoneNumber IS NULL;SELECT UsernameFROM ProfilesWHERE PhoneNumber IS NOT NULL;Task 1:
| Username |
|---|
| data_queen |
| ghost |
Task 2:
| Username |
|---|
| tech_guy |
| sql_pro |
Where does NULL go when you sort?
NULL values are treated as “larger” than all other values by default (they appear last in ASC and first in DESC).NULL values are treated as “smaller” (they appear first in ASC).Most databases allow you to override this using ORDER BY column_name ASC NULLS FIRST or NULLS LAST.
By default, most B-Tree indexes include NULL values. However, some databases (like Oracle) do not index rows where all indexed columns are NULL. This can lead to unexpected Full Table Scans if you query for IS NULL.
Almost all aggregate functions (like SUM, AVG, COUNT) ignore NULL values. The only exception is COUNT(*), which counts every row regardless of content.