loading..
Русский    English
15:56
листать

Использование значения 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

Bookmark and Share
Тэги:
ALL AND AUTO_INCREMENT AVG battles CASE CAST CHAR CHARINDEX CHECK classes COALESCE CONSTRAINT Convert COUNT CROSS APPLY CTE DATEADD DATEDIFF DATENAME DATEPART DATETIME DDL DEFAULT DELETE DISTINCT DML EXCEPT EXISTS EXTRACT FOREIGN KEY FROM FULL JOIN GROUP BY Guadalcanal HAVING IDENTITY IN INNER JOIN insert INTERSECT IS NOT NULL IS NULL ISNULL laptop LEFT LEFT OUTER JOIN LEN maker MAX Больше тэгов
Учебник обновлялся
сегодня
©SQL-EX,2008 [Развитие] [Связь] [О проекте] [Ссылки] [Team]
Перепечатка материалов сайта возможна только с разрешения автора.
Rambler's Top100