Читать книгу Самоучитель. Курс SQL. Базы данных. ORACLE - - Страница 14
8. Правильное обращение с NULL («пустыми» значениями)
ОглавлениеЭто еще одна очень важная тема! Ее знание не просто так спрашивают на собеседованиях! Выберем из таблицы CanteenDishes («Блюда столовой») строчки. Для повторения темы сортировки, заодно, упорядочим выбираемые блюда по цене в обратном порядке:
Получаем:
Здесь нужно обратить внимание на столбец «CookID» («Идентификатор повара»). Из всего ассортимента блюд нашей столовой, есть блюда, идентификатор повара у которых не заполнен. Значение в графе CookID пустое. Для таких строчек в этом столбце программа SQL Developer выводит нам «(null)». Важным моментом здесь является то, как выбирать данные, опираясь на этот столбец.
Представим, что перед нами стоит задача вывести все блюда, которые не готовятся в нашей столовой, то есть те, где не указан повар (CookID). Например, пирожное Тирамиссу повара нашей платной столовой сами не готовят. Оно закупное из продовольственной базы. Или, например, питьевая минеральная вода (не попала на скриншоте выше, не уместилась, так как отображены не все строчки). Ее также привозят в больших объемах в маленьких бутылочках и продают в столовой.
Итак, чтобы отобрать строчки из таблицы, где значение в это графе пустое, мы не можем написать запрос вида:
Вернее можем, но при попытке выполнить его, получим пустой набор данных. Все из–за того, что при сравнении с NULL операторы «равно» и «не равно» не допустимы. Результат всегда будет «Ложь».
Чтобы выбрать блюда столовой с проверкой на NULL в столбце CookID, необходимо использовать оператор IS или IS NOT. Корректируем предыдущий пример:
И вот они, данные:
Мы отобрали все блюда, у которых в графе CookID пусто (NULL). Если бы нам нужно было, наоборот, вывести блюда, у которых CookID указан, то мы бы написали:
Получить данные по блюдам, у которых указан CookID мы можем, также и запросом:
Строчки с пустым CookID не попадут в результирующий набор данных. Данная команда даст результат (мы увидим список блюд, у которых указан идентификатор повара), так как в нашем запросе значение графы CookID сравнивается с 0, а не с NULL. И поэтому можно обойтись и без IS или IS NOT. Только если нам нужно отобрать строки с пустым CookID, то тут, конечно, без IS NULL не обойтись.
С NULL не только нельзя сравнивать с помощью операторов «равно» и «не равно», но и нельзя применять арифметические операции, иначе результатом будет NULL. Ниже один из любимых вопросов на собеседовании по SQL на понимание принципов работы с NULL:
Правильным вариантом является только номер 5.
Обрати внимание, что в заголовке этой темы, я во фразе «пустые» значения слово «пустые» взял в кавычки. Это для того, чтобы показать тебе, что хоть при наличии значения NULL в каком-то столбце некоторой записи пусто, NULL обычно трактуется не сколько как пустота, сколько как неопределенность. Вот поэтому при прямом сравнении NULL = NULL будет ответ ложь (false), так как одна неопределенность не может быть равна другой неопределенности, ведь мы не знаем, что скрывается ни под одной из неопределенностей.