SQL Tutorial · Chapter 13 of 32
SQL NULL values represent missing or unknown data. NULL is not zero, not an empty string and not FALSE: it is the absence of a value. Because NULL is unknown, ordinary comparisons such as = NULL never return TRUE. You test for it with IS NULL and IS NOT NULL, and you replace it with a default using COALESCE.
SQL NULL Syntax
SELECT columns FROM table_name WHERE column IS NULL;
SELECT columns FROM table_name WHERE column IS NOT NULL;
SELECT COALESCE(column, 'default') FROM table_name;
Sample Table
For this chapter the Orders table gains a ShipDate column. Orders that have not shipped yet have no ship date, which is exactly what NULL is for.
| OrderID | CustomerID | Product | Amount | OrderDate | ShipDate |
|---|---|---|---|---|---|
| 101 | 1 | Laptop | 1200 | 2026-01-05 | 2026-01-08 |
| 102 | 2 | Mouse | 25 | 2026-01-07 | 2026-01-09 |
| 103 | 1 | Monitor | 300 | 2026-01-12 | NULL |
| 104 | 3 | Keyboard | 45 | 2026-02-02 | 2026-02-04 |
| 105 | 6 | Headset | 80 | 2026-02-15 | NULL |
| 106 | 4 | Laptop | 1150 | 2026-03-01 | NULL |
Example 1: Find Missing Values with IS NULL
SELECT OrderID, Product
FROM Orders
WHERE ShipDate IS NULL;
| OrderID | Product |
|---|---|
| 103 | Monitor |
| 105 | Headset |
| 106 | Laptop |
These are the unshipped orders. Writing WHERE ShipDate = NULL instead returns zero rows in every database, because the comparison evaluates to unknown.
Example 2: Find Present Values with IS NOT NULL
SELECT OrderID, ShipDate
FROM Orders
WHERE ShipDate IS NOT NULL;
| OrderID | ShipDate |
|---|---|
| 101 | 2026-01-08 |
| 102 | 2026-01-09 |
| 104 | 2026-02-04 |
Example 3: Replace NULL with COALESCE
COALESCE returns the first non-NULL argument. It is the standard way to show a friendly label instead of a blank.
SELECT OrderID, COALESCE(ShipDate, 'Not shipped') AS ShipStatus
FROM Orders;
| OrderID | ShipStatus |
|---|---|
| 101 | 2026-01-08 |
| 102 | 2026-01-09 |
| 103 | Not shipped |
| 104 | 2026-02-04 |
| 105 | Not shipped |
| 106 | Not shipped |
In a strictly typed database such as PostgreSQL or SQL Server, cast the date to text first: COALESCE(CAST(ShipDate AS VARCHAR), 'Not shipped').
Example 4: NULL in Arithmetic
Any calculation involving NULL produces NULL. Here we compute shipping days; unshipped orders come out as NULL rather than a number.
SELECT OrderID, julianday(ShipDate) - julianday(OrderDate) AS DaysToShip
FROM Orders; -- SQLite syntax; see dialect notes
| OrderID | DaysToShip |
|---|---|
| 101 | 3 |
| 102 | 2 |
| 103 | NULL |
| 104 | 2 |
| 105 | NULL |
| 106 | NULL |
Example 5: NULL and Aggregate Functions
COUNT(column), SUM, AVG, MIN and MAX all skip NULLs. Only COUNT(*) counts every row.
SELECT COUNT(*) AS AllOrders, COUNT(ShipDate) AS Shipped
FROM Orders;
| AllOrders | Shipped |
|---|---|
| 6 | 3 |
Three-Valued Logic
SQL conditions can be TRUE, FALSE or UNKNOWN. A WHERE clause keeps only TRUE rows, so an UNKNOWN result behaves like FALSE. This is why NOT IN with a NULL in the list returns nothing, and why Amount <> 100 silently drops rows where Amount is NULL.
Works in MySQL, SQL Server, PostgreSQL, SQLite
IS NULL,IS NOT NULLandCOALESCEare standard in all four.- Shortcuts: MySQL
IFNULL(a, b), SQL ServerISNULL(a, b), OracleNVL(a, b), SQLiteIFNULL(a, b). COALESCE is the portable choice. - Date arithmetic differs: MySQL
DATEDIFF(ShipDate, OrderDate), SQL ServerDATEDIFF(day, OrderDate, ShipDate), PostgreSQLShipDate - OrderDate. - Empty string vs NULL: Oracle treats ” as NULL; the four databases here do not.
Designing for NULL
Allow NULL only where a value can genuinely be unknown, such as a ship date before shipping, and declare columns NOT NULL everywhere else. Fewer nullable columns mean fewer IS NULL checks, fewer COALESCE wrappers and fewer surprising empty results from NOT IN. When a default makes sense, such as 0 for a quantity, set it in the table definition rather than storing NULL.
Common Mistakes
- Writing
= NULLor<> NULL; always use IS NULL / IS NOT NULL. - Expecting AVG to treat NULL as zero. It ignores the row entirely, which changes the denominator.
- Concatenating text with a NULL column and getting NULL for the whole string (except in SQL Server with CONCAT).
- Storing 0 or ‘N/A’ instead of NULL and then averaging the fake values.
Practice Exercise
- Count how many orders have not shipped.
- Show OrderID and ShipDate, displaying ‘Pending’ where the ship date is missing.
Show answers
-- 1
SELECT COUNT(*) AS Unshipped FROM Orders WHERE ShipDate IS NULL;
-- 3
-- 2
SELECT OrderID, COALESCE(ShipDate, 'Pending') AS ShipDate FROM Orders;
Related Chapters
- SQL WHERE – the clause where IS NULL lives
- SQL COUNT, AVG, SUM – how aggregates skip NULL
- SQL LEFT JOIN – where NULLs appear for unmatched rows
- SQL from Scratch: full course overview
FAQ
What is a NULL value in SQL?
NULL means a value is missing or unknown. It is a marker, not a value, so it is different from 0, an empty string or FALSE.
Why does WHERE column = NULL return no rows?
Comparing anything with NULL gives UNKNOWN, not TRUE, and WHERE keeps only TRUE rows. Use IS NULL instead.
What is the difference between COALESCE and ISNULL?
COALESCE is standard SQL, accepts any number of arguments and works in every database. ISNULL (SQL Server) and IFNULL (MySQL, SQLite) take exactly two arguments and are vendor specific.
Chapter 13 of 32 · SQL from Scratch: all 32 chapters



