loading..
Русский    English
06:14
листать

Использование значения NULL в условиях поиска

Предикат:

  1. IS [NOT] NULL
позволяет проверить отсутствие (наличие) значения в полях таблицы. Использование в этих случаях обычных предикатов сравнения может привести к неверным результатам, так как сравнение со значением NULL дает результат UNKNOWN (неизвестно).

Так, если требуется найти записи в таблице PC, для которых в столбце price отсутствует значение (например, при поиске ошибок ввода), можно воспользоваться следующим оператором:

Консоль
Выполнить
  1. SELECT *
  2. FROM PC
  3. WHERE price IS NULL

Характерной ошибкой является написание предиката в виде:

  1. WHERE price = NULL;

Этому предикату не соответствует ни одной строки, поэтому результирующий набор записей будет пуст, даже если имеются изделия с неизвестной ценой. Это происходит потому, что сравнение с NULL-значением согласно предикату сравнения оценивается как UNKNOWN. А строка попадает в результирующий набор только в том случае, если предикат в предложении WHERE есть TRUE. Это же справедливо и для предиката в предложении HAVING.

Аналогичной, но не такой очевидной ошибкой является сравнение с NULL в предложении CASE (см. пункт 5.10). Чтобы продемонстрировать эту ошибку, рассмотрим такую задачу: «Определить год спуска на воду кораблей из таблицы Outcomes. Если последний неизвестен, указать 1900».

Поскольку год спуска на воду (launched) находится в таблице Ships, нужно выполнить левое соединение (см. пункт 5.6):

Консоль
Выполнить
  1. SELECT ship, launched
  2. FROM Outcomes o LEFT JOIN
  3. Ships s ON o.ship = s.name;

Для кораблей, отсутствующих в Ships, столбец launched будет содержать NULL-значение. Теперь попробуем заменить это значение значением 1900 с помощью оператора CASE (см. пункт 5.10):

Консоль
Выполнить
  1. SELECT ship, CASE launched
  2. WHEN NULL
  3. THEN 1900
  4. ELSE launched
  5. END 'year'
  6. FROM Outcomes o LEFT JOIN
  7. Ships s ON o.ship=s.name;

Однако ничего не изменилось. Почему? Потому что использованный оператор CASE эквивалентен следующему:

  1. CASE
  2. WHEN launched = NULL
  3. THEN 1900
  4. ELSE launched
  5. END 'year';

А здесь мы получаем сравнение с NULL-значением, и в результате — UNKNOWN, что приводит к использованию ветви ELSE, и все остается, как и было. Правильным будет следующее написание:

  1. CASE
  2. WHEN launched IS NULL THEN 1900
  3. ELSE launched
  4. END 'year';
то есть проверка именно на присутствие NULL-значения.

Рекомендуемые упражнения: 43, 52, 59, 64, 75

Тэги:
ALL AVG battles CASE CAST CHAR CHARINDEX classes COALESCE Convert COUNT CTE DATEDIFF DATEPART DATETIME DELETE DISTINCT EXCEPT EXISTS EXTRACT FROM FULL JOIN GROUP BY Guadalcanal HAVING IN INNER JOIN insert INTERSECT ISNULL laptop LEFT LEFT OUTER JOIN LEN maker MAX MIN MySQL NOT IN NULL ORDER BY Outcome outcomes OVER PARTITION BY pc PIVOT PostgreSQL printer product Больше тэгов
Учебник обновлялся
несколько дней назад
©SQL-EX,2008 [Развитие] [Связь] [О проекте] [Ссылки] [Team]
Перепечатка материалов сайта возможна только с разрешения автора.
Rambler's Top100