КАК ANY, ALL, И EXIST ПОСТУПАЮТ С ОТСУТСТВУЮЩИМИ И НЕИЗВЕСТНЫМИ ДАННЫМИ
Как было сказано, имеются некоторые различия между
EXISTS и операторами представленными в этой главе относительно того как они обрабатывают оператор NULL.
ANY и
ALL также отличаются друг от друга тем как они реагируют если подзапрос не произвел никаких значений
чтобы использовать их в сравнении. Эти различия могут привести к непредвиденным результатам на Ваши
запросы если вы не
будете их учитывать.
КОГДА ПОДЗАПРОС ВОЗВРАЩАЕТСЯ ПУСТЫМ
Одно значительное различие между ALL и ANY -
способ действия в cитуации когда подзапрос не возвращает никаких значений. В принципе, всякий раз,
когда допустимый
подзапрос не в состоянии сделать вывод, ALL - автоматически верен, а ANY автоматически неправилен. Это
означает, что
следующий запрос
SELECT * FROM Customers WHERE rating > ANY ( SELECT rating FROM Customers WHERE city = Boston );
не произведет никакого вывода, в то время как запрос -
SELECT FROM Customers WHERE rating > ALL ( SELECT rating FROM
Customers WHERE city = 'Boston' );
выведет всю таблицу Заказчиков. Когда нет никаких заказчиков в
Boston, естественно, ни
одно из этих сравнений не имеет значення.
ANY И ALL ВМЕСТО EXISTS С ПУСТЫМ УКАЗАТЕЛЕМ( NULL ) Значения
NULL также имеют некоторые проблемы с операторами наподобие этих. Когда SQL сравнивает два значения в
предикате,
одно из которых пустое (NULL), то результат неизвестен . Неизвестный предикат, подобен неверному и
является причиной того что строка не выбирается, но работать он будет иначе в некоторых похожих
запросах, в зависимости
от того, используют они ALL или ANY вместо EXISTS. Рассмотрим наш предыдущий пример:
SELECT * FROM Customers
WHERE rating > ANY ( SELECT rating FROM Customers WHERE city = 'Rome' );
и еще один пример:
SELECT * FROM Customers
outer WHERE EXISTS ( SELECT * FROM Customers inner WHERE outer.rating > inner.rating AND inner.city = 'Rome' );
В общем, эти
два запроса будут вести себя одинаково. Но предположим, что появилось пустое(NULL) значение в столбце
rating таблицы
Заказчиков: CNUM CNAME CITY RATING SNUM 2003 Liu SanJose NULL 1002 В варианте с ANY, где оценка Liu
выбрана
основным запросом, значение NULL делает предикат неизвестным а строка Liu не выбирается для вывода.
Однако, в
варианте с NOT EXISTS когда эта строка выбрана основным запросом, значение NULL используется в
предикате подзапроса,
делая его неизвестным в каждом случае. Это означает что подзапрос не будет производить никаких значений,
и EXISTS
будет неправилен. Это, естественно, делает оператор NOT EXISTS верным. Следовательно, строка Liu будет
выбрана для
вывода. Это основное расхождение, в отличие от других типов предикатов, где значение EXISTS независимо
от того верно
оно или нет - всегда неизвестно. Все это является аргументом в пользу использования варианта формулировки
с ANY. Мы
не считаем что значение NULL является выше чем допустимое значение. Более того, результат будет тот же,
если мы будем
проверять для более низкого значения.