В этой лекции мы ещё лучше узнаем загадочного знакомца NULL. Конечно, ваши собственные ошибки при работе с инм ещё впереди, но... предупреждён — вооружён. Разберём несколько типичных ошибок, связанных с NULL.
Ошибка 1: Использование обычного оператора = для проверки NULL
Пожалуй, самая популярная ошибка среди новичков в SQL — попытка использовать оператор = для проверки, равно ли значение NULL.
Что происходит?
SELECT *
FROM students
WHERE age = NULL;
Наивно полагая, что это покажет всех студентов с неопределённым возрастом, вы будете разочарованы: этот запрос не вернёт ничего. Почему? Всё дело в том, что NULL не является значением, а значит, обычные операторы сравнения с ним не работают. Как говорится в волшебной книге SQL: "NULL ни с чем нельзя сравнивать напрямую".
Как должно быть?
Для проверки, является ли значение NULL, используйте IS NULL:
SELECT *
FROM students
WHERE age IS NULL;
Теперь вы получите всех студентов, возраст которых не указан.
Ошибка 2: Агрегатные функции игнорируют NULL (кроме COUNT(*))
Когда выполняются запросы с агрегатными функциями, NULL автоматически исключается из расчётов. Это может привести к неожиданным результатам.
Что происходит?
SELECT AVG(salary) AS avg_salary
FROM employees;
Если в колонке salary есть NULL, такие строки просто игнорируются, и средняя зарплата будет рассчитана без учёта этих записей. Это может создать ложное представление о средней заработной плате.
Как избежать?
Прежде чем выполнять агрегирование, убедитесь, что вы корректно заменяете NULL на значение по умолчанию. Например, используйте COALESCE():
SELECT AVG(COALESCE(salary, 0)) AS avg_salary
FROM employees;
Теперь NULL-значения будут заменены на 0 перед расчетом.
Ошибка 3: Сравнение NULL между собой
В базе данных NULL не равно буквально ничему, даже другому NULL. Это может быть неожиданностью.
Что происходит?
SELECT *
FROM students
WHERE NULL = NULL;
Этот запрос тоже вернёт пустой результат. Почему? Потому что SQL считает, что отсутствие одного значения не может быть "равным" отсутствию другого. Да, SQL — философский язык.
Как должно быть?
Если нужно проверить два NULL на "равенство", используйте специальные конструкции вроде IS NULL. Например:
SELECT *
FROM students
WHERE first_name IS NULL AND last_name IS NULL;
Ошибка 4: Деление на NULL
Деление на NULL — это не просто ошибка, а своего рода математическое преступление, которое SQL карает бессмысленным результатом — NULL.
Что происходит?
SELECT 10 / NULL AS result;
Результат? NULL. SQL отказывается даже пытаться понять, что вы от него хотите.
Как избежать?
Чтобы обезопасить свои запросы от подобных недоразумений, используйте COALESCE() или NULLIF():
SELECT 10 / COALESCE(divisor, 1) AS result
FROM calculations;
В этом запросе, если divisor окажется NULL, вместо деления на NULL будет деление на 1.
Ошибка 5: Неработающие логические операторы с NULL
NULL ломает логику, как только встречается в выражениях. Например, условие TRUE AND NULL вернёт NULL, а не TRUE или FALSE.
Что происходит?
SELECT *
FROM students
WHERE age > 18 OR age = NULL;
В этом случае даже если age > 18 истинно для некоторых записей, часть строк с NULL в колонке age может быть исключена из результата. Почему? Потому что часть выражения age = NULL будет возвращать NULL, а не TRUE.
Как должно быть?
Всегда явно обрабатывайте NULL значения в логических условиях:
SELECT *
FROM students
WHERE age > 18 OR age IS NULL;
Ошибка 6: Неявное поведение при сортировке NULL (наиболее "тяжелая" ошибка)
Если в запросе используется ORDER BY, поведение NULL может вас удивить. По умолчанию PostgreSQL сортирует строки с NULL-значениями в конце при сортировке по возрастанию и в начале при сортировке по убыванию.
Что происходит?
SELECT product_name, price
FROM products
ORDER BY price;
Если price имеет NULL, эти строки будут отображаться в конце списка.
Как избежать неожиданностей?
Вы можете явно указать сортировку для NULL с помощью NULLS FIRST или NULLS LAST:
SELECT product_name, price
FROM products
ORDER BY price NULLS FIRST;
Ошибка 7: Неправильная работа с внешними ключами и NULL
NULL значения в столбцах с внешними ключами могут иногда приводить к неожиданному поведению.
Что происходит?
Если вы добавили внешние ключи в таблицу и пытаетесь вставить строку, оставив поле внешнего ключа пустым, PostgreSQL не подаст признаков жизни. Это связано с тем, что NULL-значения не проверяются на соответствие в связанным таблицам.
Как работать правильно?
Используйте ограничения NOT NULL, если хотите исключить возможность использования NULL в таких полях. Или просто учтите, что NULL значения остаются "сиротами", не принадлежащими ни одной из связанных таблиц.
Подробнее про связанные таблицы и внешние ключи вы узнаете в следующей лекции :P
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ