<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. SQL
  3. Foundations
All lessons in this course

Lesson 5 of 54 14 minBeginner

NULL and three-valued logic

NULL means “unknown”, not zero or empty. See why `= NULL` never matches, how NULL spreads through expressions, the NOT IN trap, and the functions that replace NULL with a real value.

Some BuildMart customers have not given a phone number, an email address or even a city. Those cells hold NULL: a marker that means no value is known. NULL is not zero, and it is not empty text (N''). It is the absence of a value.

Query.sql
SELECT FirstName, City, Email, PhoneFROM dbo.Customers;
Output
FirstName  City       Email              Phone
---------  ---------  -----------------  -------------
Asha       Leeds      asha@example.com   0113 496 0001
Ben        York       NULL               01904 555 010
Chloe      Leeds      chloe@example.com  NULL
Dev        Bradford   dev@example.com    01274 555 220
Ella       NULL       ella@example.com   NULL
Farid      York       farid@example.com  01904 555 777
Grace      Leeds      NULL               NULL
Zoë        Harrogate  zoe@example.com    01423 555 123

Three-valued logic

Is an unknown city equal to Leeds? SQL Server cannot say yes or no, so the answer is a third truth value: UNKNOWN. Any comparison with NULL (=, <>, <, …) gives UNKNOWN. WHERE keeps a row only when the condition is TRUE, so UNKNOWN rows are dropped, exactly like FALSE ones.

Interactive

TRUE, FALSE and UNKNOWN

SELECT FirstName, City, Email, Phone FROM dbo.Customers WHERE …
FirstNameCityEmailPhoneCondition is
1AshaLeedsasha@example.com0113 496 0001FALSE
2BenYorkNULL01904 555 010TRUE
3ChloeLeedschloe@example.comNULLFALSE
4DevBradforddev@example.com01274 555 220TRUE
5EllaNULLella@example.comNULLUNKNOWN
6FaridYorkfarid@example.com01904 555 777TRUE
7GraceLeedsNULLNULLFALSE
8ZoëHarrogatezoe@example.com01423 555 123TRUE
4 of 8 rows returned. Ella is missing here too. She is in neither “Leeds” nor “not Leeds”: the two queries together return 7 rows, not 8.

IS NULL, not = NULL

= NULL asks “is this equal to an unknown value?”, which is always UNKNOWN, so this query returns no rows at all, even though three customers have no phone:

Query.sql
SELECT FirstName, PhoneFROM dbo.CustomersWHERE Phone = NULL;
Output
FirstName  Phone
---------  -----

The right test is IS NULL (or IS NOT NULL). It asks “is a value missing?”, which always has a TRUE or FALSE answer:

Query.sql
SELECT FirstName, PhoneFROM dbo.CustomersWHERE Phone IS NULL;
Output
FirstName  Phone
---------  -----
Chloe      NULL
Ella       NULL
Grace      NULL

The missing row

Ella’s city is NULL. Ask for customers in Leeds and she is not there. Ask for customers not in Leeds and she is still not there:

Query.sql
SELECT FirstName, CityFROM dbo.CustomersWHERE City <> N'Leeds';
Output
FirstName  City
---------  ---------
Ben        York
Dev        Bradford
Farid      York
Zoë        Harrogate

Three customers live in Leeds and four live elsewhere, which adds up to 7 of the 8. Whenever a column allows NULL, a condition and its opposite do not cover every row. Decide where the NULL rows belong and say so: WHERE City <> N'Leeds' OR City IS NULL.

NULL spreads through expressions

Arithmetic or + with a NULL gives NULL: 5 plus an unknown number is unknown. CONCAT is the exception; it treats NULL as empty text.

Query.sql
SELECT 5 + NULL AS AddNull,       N'Phone: ' + NULL AS PlusNull,       CONCAT(N'Phone: ', NULL) AS ConcatNull;
Output
AddNull  PlusNull  ConcatNull
-------  --------  ----------
   NULL  NULL      Phone:

Replacing NULL: ISNULL and COALESCE

ISNULL(x, fallback) returns x, or the fallback when x is NULL. COALESCE(a, b, c, …) returns the first value in its list that is not NULL, so it can try several columns in turn:

Query.sql
SELECT FirstName,       ISNULL(City, N'(unknown)') AS City,       COALESCE(Phone, Email, 'no contact details') AS BestContactFROM dbo.Customers;
Output
FirstName  City       BestContact
---------  ---------  ------------------
Asha       Leeds      0113 496 0001
Ben        York       01904 555 010
Chloe      Leeds      chloe@example.com
Dev        Bradford   01274 555 220
Ella       (unknown)  ella@example.com
Farid      York       01904 555 777
Grace      Leeds      no contact details
Zoë        Harrogate  01423 555 123

Grace has neither a phone nor an email, so COALESCE falls through to the text at the end. COALESCE is standard SQL and takes any number of arguments; ISNULL is T-SQL only and takes exactly two. NULLIF(a, b) goes the other way: it returns NULL when a equals b, which is handy to avoid dividing by zero: x / NULLIF(Stock, 0).

The NOT IN trap

City NOT IN (N'Leeds', NULL) means City <> N'Leeds' AND City <> NULL. The second test is always UNKNOWN, so the whole condition can never be TRUE:

Query.sql
SELECT FirstName, CityFROM dbo.CustomersWHERE City NOT IN (N'Leeds', NULL);
Output
FirstName  City
---------  ----
ExpressionResult
NULL = NULLUNKNOWN
NULL <> 5UNKNOWN
NULL IS NULLTRUE
TRUE AND UNKNOWNUNKNOWN
FALSE AND UNKNOWNFALSE
TRUE OR UNKNOWNTRUE
NOT UNKNOWNUNKNOWN
5 + NULLNULL
Quick check

How many rows does SELECT * FROM dbo.Customers WHERE Email = NULL; return?

Quick check

What is COALESCE(NULL, NULL, N'x', N'y')?

Quick check

FALSE AND UNKNOWN is…

Practice

Find the customers who have a city but no email address, so the shop can post them a catalogue. Show FirstName, LastName and City, plus a Phone column that shows (none) when the phone is missing.

Show a hint

Two NULL tests joined with AND: one IS NOT NULL, one IS NULL. Use ISNULL for the phone column.

Show the solution
Solution.sql
SELECT FirstName, LastName, City, ISNULL(Phone, '(none)') AS PhoneFROM dbo.CustomersWHERE City IS NOT NULL AND Email IS NULL;
Output
FirstName  LastName  City   Phone
---------  --------  -----  -------------
Ben        Carter    York   01904 555 010
Grace      Lee       Leeds  (none)

Remember

  • NULL means unknown or missing: not zero, not empty text.
  • Comparisons with NULL give UNKNOWN, and WHERE keeps only TRUE rows, so test with IS NULL / IS NOT NULL.
  • A condition and its opposite miss the NULL rows; decide where they belong.
  • NULL spreads through + and arithmetic; CONCAT treats it as empty text.
  • ISNULL and COALESCE replace NULL with a value; NOT IN with a NULL in the list returns nothing.
0 of 54 lessons completed