MySQL IS NULL Condition
In SQL, NULL marks a value that is missing or unknown: a patient who hasn't been discharged yet, a phone number nobody gave. NULL isn't zero and isn't an empty string, and it can't be found with =. The IS NULL condition is how you find it.
1. Why = NULL Doesn't Work
IS NULL.Table: patients (5 rows)
| id | name | phone | discharge_date | bill | insurer | |
|---|---|---|---|---|---|---|
| 1 | Anil | 98450 11111 | anil@mail.example | 2026-03-02 | 18500.00 | StarCare |
| 2 | Bina | NULL | bina@mail.example | NULL | NULL | NULL |
| 3 | Cyril | 99000 22222 | NULL | 2026-03-05 | 7200.00 | NULL |
| 4 | Dolly | NULL | NULL | NULL | 32000.00 | HealthPlus |
| 5 | Emil | 97300 33333 | 2026-03-07 | 4100.00 | StarCare |
SELECT name FROM patients WHERE phone = NULL;
= NULL: always empty
| name |
|---|
| No rows |
SELECT name FROM patients WHERE phone IS NULL;
IS NULL: correct
| name |
|---|
| Bina |
| Dolly |
2. Syntax
expression IS NULL
expression IS NOT NULL
SELECT NULL = NULL AS eq, NULL IS NULL AS is_null, 0 IS NULL AS zero, '' IS NULL AS empty_string;
Result: 1 row
| eq | is_null | zero | empty_string |
|---|---|---|---|
| NULL | 1 | 0 | 0 |
3. Finding Missing Data
SELECT name FROM patients WHERE discharge_date IS NULL; -- still admitted
Result: 2 rows
| name |
|---|
| Bina |
| Dolly |
SELECT name FROM patients WHERE phone IS NULL AND email IS NULL; -- no way to contact
Result: 1 row
| name |
|---|
| Dolly |
Emil's email is an empty string, which is not NULL. To treat empty strings as missing too:
SELECT name, email FROM patients WHERE email IS NULL OR email = '';
Result: 3 rows
| name | |
|---|---|
| Cyril | NULL |
| Dolly | NULL |
| Emil |
SELECT name FROM patients WHERE NULLIF(email, '') IS NULL; -- same thing, shorter
Result: 3 rows
| name |
|---|
| Cyril |
| Dolly |
| Emil |
4. IS NULL in UPDATE and DELETE
UPDATE patients SET insurer = 'Self-pay' WHERE insurer IS NULL AND bill IS NOT NULL;
SELECT name, insurer FROM patients;
Result: 5 rows
| name | insurer |
|---|---|
| Anil | StarCare |
| Bina | NULL |
| Cyril | Self-pay |
| Dolly | HealthPlus |
| Emil | StarCare |
UPDATE … SET col = NULL is correct: in SET, = is assignment, not comparison.5. Replacing NULLs: IFNULL, COALESCE, NULLIF
| Function | Returns | Example |
|---|---|---|
IFNULL(a, b) | a, or b if a is NULL | IFNULL(phone, 'n/a') |
COALESCE(a, b, c, …) | The first non-NULL argument (standard SQL) | COALESCE(phone, email, 'none') |
NULLIF(a, b) | NULL if a = b, else a | NULLIF(email, '') |
ISNULL(a) | 1 if a is NULL, else 0 | ISNULL(bill) |
SELECT name,
IFNULL(phone, 'n/a') AS phone,
COALESCE(phone, NULLIF(email, ''), 'none') AS best_contact,
IFNULL(bill, 0) AS bill_or_zero
FROM patients;
Result: 5 rows
| name | phone | best_contact | bill_or_zero |
|---|---|---|---|
| Anil | 98450 11111 | 98450 11111 | 18500.00 |
| Bina | n/a | bina@mail.example | 0.00 |
| Cyril | 99000 22222 | 99000 22222 | 7200.00 |
| Dolly | n/a | none | 32000.00 |
| Emil | 97300 33333 | 97300 33333 | 4100.00 |
6. The NULL-Safe Equal Operator <=>
<=> works like = but treats two NULLs as equal and never returns NULL. Handy when comparing two columns that may be NULL:
SELECT NULL <=> NULL AS both_null, 'x' <=> NULL AS one_null, 'x' <=> 'x' AS equal;
Result: 1 row
| both_null | one_null | equal |
|---|---|---|
| 1 | 0 | 1 |
SELECT name FROM patients WHERE insurer <=> NULL;
Result: 1 row
| name |
|---|
| Bina |
7. NULLs in Aggregates and Arithmetic
Aggregate functions skip NULLs (except COUNT(*)). Any arithmetic with NULL gives NULL:
SELECT COUNT(*) AS patients, COUNT(bill) AS with_bill, SUM(bill) AS total, AVG(bill) AS avg_known, AVG(IFNULL(bill, 0)) AS avg_as_zero FROM patients;
Result: 1 row
| patients | with_bill | total | avg_known | avg_as_zero |
|---|---|---|---|---|
| 5 | 4 | 61800.00 | 15450.000000 | 12360.000000 |
SELECT 100 + NULL AS plus, CONCAT('Ward ', NULL) AS concat_null, CONCAT_WS(' ', 'Ward', NULL, 'B') AS concat_ws;
Result: 1 row
| plus | concat_null | concat_ws |
|---|---|---|
| NULL | NULL | Ward B |
8. NULLs in ORDER BY and GROUP BY
SELECT name, discharge_date FROM patients ORDER BY discharge_date;
Result: 5 rows
| name | discharge_date |
|---|---|
| Bina | NULL |
| Dolly | NULL |
| Anil | 2026-03-02 |
| Cyril | 2026-03-05 |
| Emil | 2026-03-07 |
NULLs sort first in ascending order and form one group in GROUP BY:
SELECT discharge_date IS NULL AS still_admitted, COUNT(*) AS patients FROM patients GROUP BY discharge_date IS NULL;
Result: 2 rows
| still_admitted | patients |
|---|---|
| 0 | 3 |
| 1 | 2 |
9. IS NULL Can Use an Index
CREATE INDEX idx_discharge ON patients (discharge_date);
EXPLAIN SELECT name FROM patients WHERE discharge_date IS NULL;
Result: 1 row
| type | key | Extra |
|---|---|---|
| ref | idx_discharge | Using index condition |
10. Practice Exercises
Exercise 1: Patients without a phone number, showing their email or 'no contact'.
SELECT name, COALESCE(NULLIF(email, ''), 'no contact') AS contact
FROM patients WHERE phone IS NULL;
Result: 2 rows
| name | contact |
|---|---|
| Bina | bina@mail.example |
| Dolly | no contact |
Exercise 2: Show each patient's discharge date, or 'Admitted' if there is none.
SELECT name, COALESCE(DATE_FORMAT(discharge_date, '%d %b %Y'), 'Admitted') AS status FROM patients;
Result: 5 rows
| name | status |
|---|---|
| Anil | 02 Mar 2026 |
| Bina | Admitted |
| Cyril | 05 Mar 2026 |
| Dolly | Admitted |
| Emil | 07 Mar 2026 |
11. Summary
- NULL means unknown; any comparison with NULL using =, <>, < or > gives NULL.
- Use
IS NULL/IS NOT NULLto test for it. - Empty strings and 0 are values, not NULL; NULLIF turns them into NULL when needed.
- IFNULL and COALESCE supply defaults; <=> compares NULL-safely.
- Aggregates skip NULLs; arithmetic with NULL gives NULL.