Трёхзначная логика. В SQL есть TRUE, FALSE и UNKNOWN. Сравнение с NULL (=, <>, >) даёт UNKNOWN, а WHERE пропускает только TRUE. Поэтому WHERE middle_name = NULL не вернёт ничего, а WHERE middle_name <> 'А' не вернёт строки с NULL.
Правильно: IS NULL, IS NOT NULL, а для сравнения двух значений с учётом NULL — IS DISTINCT FROM / IS NOT DISTINCT FROM.
Агрегаты: sum, avg, min, max, count(колонка) игнорируют NULL; count(*) считает все строки. Среднее по колонке с NULL — среднее по непустым значениям. Сумма пустого множества — NULL, а не 0.
Ловушка NOT IN: если подзапрос вернул хотя бы один NULL, x NOT IN (…) для любого x даёт UNKNOWN — результат пуст. Надёжнее NOT EXISTS.
Ещё: NULL в сортировке идут в конце (PostgreSQL, по возрастанию) или в начале — управляется NULLS FIRST/LAST; в UNIQUE несколько NULL допустимы; COALESCE возвращает первый не-NULL аргумент.