SQL NULL Values
Chapter 9 of 40 · Estimated read time: 8 min
What is NULL?
NULL is not zero. NULL is not an empty string. NULL means the value is unknown or missing. A customer whose phone number has not been collected has NULL in the phone column — not 0, not a blank space.
''
Empty string
A value exists — it just has no characters
0
Zero
A value exists — it is the number zero
NULL
NULL
No value exists at all — completely absent
Real-world example: A new customer signed up but skipped the phone field. Their phone column is NULL — not "no phone", just "we don't know". This matters because queries that filter for phone numbers must handle NULL explicitly.
IS NULL and IS NOT NULL
-- Find rows where a value IS missing
WHERE column IS NULL
-- Find rows where a value IS present
WHERE column IS NOT NULL
Suppose some customers haven't provided their email:
-- Find customers who have NOT provided their email SELECT customer_id, customer_name, city FROM customers WHERE email IS NULL;
OUTPUT ↓
| customer_id | customer_name | city |
|---|---|---|
| C05 | Arjun Singh | Bengaluru |
-- Find customers who HAVE provided their email SELECT customer_id, customer_name, email FROM customers WHERE email IS NOT NULL;
OUTPUT ↓
| customer_id | customer_name | |
|---|---|---|
| C01 | Amit Verma | amit@example.com |
| C02 | Priya Sharma | priya@example.com |
| C03 | Rohan Mehta | rohan@example.com |
| C04 | Sneha Gupta | sneha@example.com |
The Most Common NULL Trap
⚠️ You cannot compare NULL using = or !=
This is because NULL = NULL evaluates to UNKNOWN, not TRUE.
WHERE email = NULL never returns any rows — not even rows where email actually is NULL.WHERE email != NULL also never returns rows.This is because NULL = NULL evaluates to UNKNOWN, not TRUE.
-- ❌ WRONG — returns 0 rows even when NULLs exist SELECT * FROM customers WHERE email = NULL; SELECT * FROM customers WHERE email != NULL; -- ✅ CORRECT — always use IS NULL / IS NOT NULL SELECT * FROM customers WHERE email IS NULL; SELECT * FROM customers WHERE email IS NOT NULL;
NULL in Calculations and Expressions
Any arithmetic involving NULL produces NULL. Think of it as "unknown + anything = still unknown":
-- If discount column has NULL, the discounted_price is also NULL SELECT product_name, price, discount, price - discount AS discounted_price -- NULL if discount is NULL FROM products; -- Fix: treat NULL discount as 0 using COALESCE SELECT product_name, price, price - COALESCE(discount, 0) AS discounted_price FROM products;
COALESCE(value, fallback) returns the first non-NULL argument.
COALESCE(discount, 0) means "use discount if it exists, otherwise use 0". You will learn more about this in the NULL Functions chapter.NULL in COUNT — A Surprising Behaviour
-- COUNT(*) counts ALL rows including those with NULLs SELECT COUNT(*) AS total_customers FROM customers; -- Result: 5 -- COUNT(column) counts only NON-NULL values in that column SELECT COUNT(email) AS customers_with_email FROM customers; -- Result: 4 (Arjun's NULL email is skipped) -- This is how you count missing values: SELECT COUNT(*) - COUNT(email) AS customers_missing_email FROM customers; -- Result: 1
Interview tip: "What is the difference between COUNT(*) and COUNT(column)?" is asked in almost every SQL interview. COUNT(*) counts rows; COUNT(column) counts non-NULL values in that column.
NULL in ORDER BY and GROUP BY
-- NULL sorting behaviour varies by database: -- PostgreSQL: NULLs go LAST in ASC, FIRST in DESC (by default) -- MySQL: NULLs go FIRST in ASC -- Control it explicitly: SELECT customer_name, email FROM customers ORDER BY email ASC NULLS LAST; -- PostgreSQL: push NULLs to the bottom -- GROUP BY treats all NULLs as one group SELECT city, COUNT(*) AS customer_count FROM customers GROUP BY city; -- A NULL city would appear as its own group
✏️ Practice Exercises
1. Find all products where the supplier_id IS NULL.
2. Count how many orders have a NULL total_amount.
3. Write a query that returns each customer's name and their email. If email is NULL, show the text "Not Provided" instead.
Show Answers
-- 1. SELECT * FROM products WHERE supplier_id IS NULL; -- 2. SELECT COUNT(*) - COUNT(total_amount) AS null_totals FROM orders; -- 3. SELECT customer_name, COALESCE(email, 'Not Provided') AS email FROM customers;