SQL NULL Values
NULL means no value: unknown, missing or not applicable. It is not zero and not an empty string, and it does not behave like a normal value. Comparisons with NULL are never true, arithmetic with NULL gives NULL, and aggregates skip it. Most “my query lost some rows” bugs come from NULLs.
- Find missing values with
IS NULLandIS NOT NULL - Why
= NULLnever matches - How NULL affects arithmetic, COUNT, DISTINCT and sorting
- The MySQL NULL-safe operator
<=>
What NULL means
In the sample data, NULL appears where a value does not exist:
- the CEO has no department and no manager;
- only sales staff have a
commission; - David Fernandes has no email.
| emp_id | first_name | dept_id | manager_id | commission |
|---|---|---|---|---|
| 100 | Meera | NULL | NULL | NULL |
| 101 | Asha | 1 | 100 | NULL |
| 102 | Rahul | 1 | 101 | NULL |
| 103 | Priya | 1 | 101 | NULL |
| 104 | Karan | 1 | 102 | NULL |
| 105 | Vikram | 2 | 100 | 12000 |
| 106 | Neha | 2 | 105 | 6000 |
| 107 | Arjun | 2 | 105 | 4500 |
| 108 | Kavya | 3 | 100 | NULL |
| 109 | Rohan | 3 | 108 | NULL |
| 110 | Sneha | 4 | 100 | NULL |
| 111 | Amit | 1 | 101 | NULL |
IS NULL and IS NOT NULL
Employees without a commission:
SELECT first_name, commissionFROM employeesWHERE commission IS NULL;| first_name | commission |
|---|---|
| Meera | NULL |
| Asha | NULL |
| Rahul | NULL |
| Priya | NULL |
| Karan | NULL |
| Kavya | NULL |
| Rohan | NULL |
| Sneha | NULL |
| Amit | NULL |
IS NULLis the only correct way to test for a missing value.- Nine employees have no commission.
Employees with a commission:
SELECT first_name, commissionFROM employeesWHERE commission IS NOT NULL;| first_name | commission |
|---|---|
| Vikram | 12000 |
| Neha | 6000 |
| Arjun | 4500 |
Why = NULL never works
SELECT first_nameFROM employeesWHERE commission = NULL;commission = NULLasks “is this value equal to an unknown value?”- The answer is always UNKNOWN, never TRUE, even when
commissionitself is NULL. WHEREkeeps only TRUE rows, so the result is an Empty set, with no error to warn you.
You can see the three-valued logic directly:
SELECT NULL = NULL AS equals, NULL <> 1 AS not_equal, NULL IS NULL AS is_null, NULL <=> NULL AS null_safe_equals;| equals | not_equal | is_null | null_safe_equals |
|---|---|---|---|
| NULL | NULL | 1 | 1 |
NULL = NULLandNULL <> 1are both NULL (unknown).IS NULLreturns a real true value: 1.<=>is MySQL’s NULL-safe equal: it treats two NULLs as equal and returns 1.
NULL in arithmetic
Any arithmetic with NULL gives NULL:
SELECT first_name, salary, commission, salary + commission AS total_payFROM employeesWHERE dept_id IN (1, 2)ORDER BY emp_id;| first_name | salary | commission | total_pay |
|---|---|---|---|
| Asha | 125000 | NULL | NULL |
| Rahul | 98000 | NULL | NULL |
| Priya | 72000 | NULL | NULL |
| Karan | 72000 | NULL | NULL |
| Vikram | 105000 | 12000 | 117000 |
| Neha | 54000 | 6000 | 60000 |
| Arjun | 48000 | 4500 | 52500 |
| Amit | 25000 | NULL | NULL |
- For the three sales staff,
salary + commissionis a real number. - For the engineers,
commissionis NULL, sosalary + NULLis NULL: their total pay disappears. - Fix it with
salary + IFNULL(commission, 0)orCOALESCE(commission, 0); see IFNULL & COALESCE.
SELECT first_name, salary + COALESCE(commission, 0) AS total_payFROM employeesWHERE dept_id IN (1, 2)ORDER BY emp_id;| first_name | total_pay |
|---|---|
| Asha | 125000 |
| Rahul | 98000 |
| Priya | 72000 |
| Karan | 72000 |
| Vikram | 117000 |
| Neha | 60000 |
| Arjun | 52500 |
| Amit | 25000 |
NULL in aggregates
Aggregate functions skip NULLs, except COUNT(*), which counts rows:
SELECT COUNT(*) AS all_rows, COUNT(commission) AS with_commission, SUM(commission) AS total_commission, AVG(commission) AS avg_commissionFROM employees;| all_rows | with_commission | total_commission | avg_commission |
|---|---|---|---|
| 12 | 3 | 22500 | 7500.0000 |
COUNT(*)counts all 12 rows.COUNT(commission)counts only the 3 non-NULL values.SUMadds 12,000 + 6,000 + 4,500 = 22,500.AVGdivides by 3 (the non-NULL count), not by 12: 7,500.
If NULL really means zero in your data, AVG(column) gives the wrong answer. Use AVG(COALESCE(commission, 0)) to average over every row.
NULL in sorting and DISTINCT
- In MySQL, NULLs sort first in ascending order and last in descending order (ORDER BY).
DISTINCTandGROUP BYtreat all NULLs as one group (DISTINCT).
SELECT dept_id, COUNT(*) AS staffFROM employeesGROUP BY dept_idORDER BY dept_id;| dept_id | staff |
|---|---|
| NULL | 1 |
| 1 | 5 |
| 2 | 3 |
| 3 | 2 |
| 4 | 1 |
NULL vs empty string vs zero
CREATE TABLE contacts (name VARCHAR(20), phone VARCHAR(15));INSERT INTO contacts VALUES ('Asha', '98450 12345'), ('Ravi', ''), ('Mona', NULL);SELECT name, phone IS NULL AS is_null, phone = '' AS is_empty, LENGTH(phone) AS lenFROM contacts;| name | is_null | is_empty | len |
|---|---|---|---|
| Asha | 0 | 0 | 11 |
| Ravi | 0 | 1 | 0 |
| Mona | 1 | NULL | NULL |
- Ravi’s phone is an empty string: a value that has zero characters.
= ''is true and the length is 0. - Mona’s phone is NULL: no value.
IS NULLis true, and both= ''andLENGTH()return NULL. - Decide on one meaning for “no phone” in your design, usually NULL, and stick to it.
NOT NULL columns
If a column must always have a value, declare it NOT NULL when you create the table, and the database will refuse missing values (NOT NULL constraint).
Exercise: Customers without email
List the customers who have no email address.
| customer_id | customer_name |
|---|---|
| 4 | David Fernandes |
Hint 1
Use IS NULL, not = NULL.
SELECT customer_id, customer_nameFROM customersWHERE email IS NULL;| customer_id | customer_name |
|---|---|
| 4 | David Fernandes |
Exercise: Total pay for everyone
Show every employee’s first_name and total_pay = salary plus commission, treating a missing commission as 0. Sort by total_pay descending.
| first_name | total_pay |
|---|---|
| Meera | 250000 |
| Asha | 125000 |
| Vikram | 117000 |
| Rahul | 98000 |
| Kavya | 88000 |
| Sneha | 78000 |
| Priya | 72000 |
| Karan | 72000 |
| Neha | 60000 |
| Arjun | 52500 |
| Rohan | 45000 |
| Amit | 25000 |
Hint 1
COALESCE(commission, 0) returns 0 when commission is NULL.
SELECT first_name, salary + COALESCE(commission, 0) AS total_payFROM employeesORDER BY total_pay DESC;| first_name | total_pay |
|---|---|
| Meera | 250000 |
| Asha | 125000 |
| Vikram | 117000 |
| Rahul | 98000 |
| Kavya | 88000 |
| Sneha | 78000 |
| Priya | 72000 |
| Karan | 72000 |
| Neha | 60000 |
| Arjun | 52500 |
| Rohan | 45000 |
| Amit | 25000 |
Quick quiz
1. Which condition finds rows where email is missing?
Only IS NULL tests for NULL.
2. What is 100 + NULL?
Arithmetic with NULL gives NULL.
3. A column has the values 10, NULL, 20. What is AVG(column)?
AVG skips NULL: (10 + 20) / 2 = 15.
4. What does NULL <=> NULL return in MySQL?
<=> is the NULL-safe equality operator.
NULL values FAQ
What is NULL in SQL?
NULL is a marker for a missing or unknown value. It is different from zero and from an empty string.
How do I check for NULL in SQL?
Use column IS NULL or column IS NOT NULL. Comparisons such as = NULL or <> NULL are never true.
Does COUNT include NULL values?
COUNT(*) counts all rows, including those with NULLs. COUNT(column) counts only rows where that column is not NULL.
How do I replace NULL with a default value?
Use COALESCE(column, default) (standard SQL) or IFNULL(column, default) in MySQL.