SELECT * FROM Ships WHERE year IS NULL.

Однако это не единственная возможность. Видимо, чтобы сделать программирование на SQL более удобным для тех, кто привык к двузначной логике традиционных языков программирования, трехзначную (по умолчанию) трактовку NULL-значений можно отключать и включать с помощью соответствующей установки параметра ANSI_NULLS:

SET ANSI_NULLS OFF|ON.

SQL имеет также трехзначный предикат X NOT IN (A, B....), где список значений поля A, B.... может содержакть NULL. Этот предикат равносилен

X <> ALL (A, B....)

или конъюнкции (трехзначной)

X <>A AND X<>B AND....

Поэтому при наличии NULL в списке он не может быть истинным (TRUE) и в предложении WHERE всегда будет давать пустой набор записей.

Когда в БД нет NULL-значений, все идет так, как и ожидает пользователь, знакомый с булевой логикой и ее представлением в SQL. Но если в БД присутствует хотя бы один NULL, ответы на те же запросы могут немало удивить того же пользователя. «Хуже того, – пишет К. Дейт, – нет никакого способа узнать, какие запросы будут выдавать неправильные результаты; все результаты становятся подозрительными. Никогда нельзя доверять ответам, которые получаются из базы данных с неопределенными значениями. По моему мнению, это состояние дел свидетельствует о невозможности использования SQL» (курсив автора).

Критику такого рода необходимо учитывать, однако Дейт сгущает краски. Кроме того, он неправ по существу, что мы покажем с помощью К. Рубинсона и других авторов, обращавшихся к этой проблематике. Но прежде отметим характерную особенность: доказывая логическую несостоятельность тезиса, что трехзначная логика нарушает реляционную модель по существу, те же авторы склонны соглашаться с практическими рекомендациями противников «третьих значений». Так, Рубинсон согласен с тем, что неопределенные значения в SQL исключительно усложняют простые на вид запросы, а переход к использованию трехзначной логики противоречит целям, для достижения которых существуют SQL- ориентированные СУБД (имеются в виду материальные затраты). Конечно, здесь сказываются ценности того мира, где стоимость выше истины, но также существенно отсутствие фундаментальных изложений трехзначной логики. Интересно, что скажет читатель по поводу логики следующего пассажа Рубинсона: «Неопределенные значения позволяют упрощать модели благодаря приведению к общей форме всех аномалий, порождающих отсутствующие данные и неизвестные связи. Но цена этого упрощенного представления – трехзначная логика и соответствующее увеличение сложности запросов».

К. Рубинсон показал, что Дейт неправильно понимает смысл запросов в своих примерах. В наиболее известных из них используется простая БД из двух таблиц, содержащих по одной записи. В таблице Suppliers (S, «поставщики») два столбца: номер поставщика (SNO, первичный ключ) и город, в котором он располагается (CITY). В таблице Parts (P, «детали») также два столбца: номер детали (PNO, первичный ключ) и город, в котором она располагается (CITY). В примере поставщик S1 располагается в Лондоне, а город, в котором находится деталь P1, неизвестен.

S   SNO*   CITY     P    PNO*    CITY

      S1    London          P1      NULL

Дейт стремится показать, что использование в SQL трехзначной логики приводит к результатам, корректным формально, но не с точки зрения реального мира. Для этого он формулирует на SQL запрос «Выдать пары SNO-PNO, для которых поставщик и деталь располагаются в разных городах, или город, в котором находится деталь, не Париж»:

SELECT S.SNO, P.PNO FROM S, P

WHERE S.CITY <> P.CITY OR P.CITY <> ‘Paris’

После подстановки данных из примерной БД условие S.CITY <> P.CITY OR P.CITY <> ‘Paris’ принимает вид (‘London’ <> NULL) OR (NULL <> ‘Paris’), при вычислении которого по правилам трехзначной логики SQL получается UNKNOWN. Следовательно, в ответ на данный запрос не возвращается ни одной записи. Дейт считает, что этот результат демонстрирует ошибку в трехзначной логике SQL, аргументируя это так:

«Но, конечно, в реальном мире детали P1 в действительности соответствует некоторый город; другими словами, „неопределенное значение атрибута CITY“ детали P1 на самом деле обозначает некоторое реальное значение, скажем xyz. Очевидно, что xyz либо равняется значению ‘Paris’, либо не равняется этому значению».

Затем Дейт показывает, что значение условного выражения WHERE всегда равно TRUE независимо от того, где располагается деталь P1. Имеются три возможности: город xyz – Париж, Лондон или еще какой- нибудь город. Если xyz=Париж, то выражение WHERE принимает вид (‘London’ <> ‘Paris’) OR (‘Paris’ <> ‘Paris’). Это выражение равно (TRUE OR FALSE), что, в свою очередь, равно TRUE. Если xyz=Лондон, то выражение WHERE принимает вид (‘London’ <> ‘London’) OR (‘London’ <> ‘Paris’), равно (FALSE OR TRUE), что равно TRUE. Если xyz какой-либо другой город, например Нью-Йорк, то выражение WHERE принимает вид (‘London’ <> ‘Нью-Йорк’) OR (‘Нью-Йорк’ <> ‘Paris’). Это выражение равно (TRUE OR TRUE), что опять равно TRUE.

По Дейту, если бы SQL правильно отражал реальный мир (в данном случае факт нахождения детали в некотором городе, несмотря на то что этот факт отсутствует в БД), то ответом на приведенный выше запрос была бы пара S1-P1. Проблема в том, что запрос Дейта предполагает традиционную двухзначную логику, а SQL имеет дело с трехзначной.

В двузначной логике высказывания бывают истинными или ложными, т. е. деталь P1 располагается в Париже или не располагается. В трехзначной логике, используемой в SQL, высказывания бывают истинными, ложными или неизвестными. С одной стороны, при допущении неизвестных высказываний деталь P1 не обязана располагаться или не располагаться в Париже; однако это имеет отношение не к реальному миру непосредственно, а к нашему представлению о нем. С другой – наше представление (знание) о мире тоже реально и потому составляет часть реального мира, а трехзначная логика – отражение этой части. Говоря языком ИТ, трехзначная логика – интерфейс между пользователем и внешним миром.

Есть основания (в том числе нейрофизиологические) полагать, что трехзначная логика выполняет данную функцию точнее, чем двузначная, хотя бы в некоторых случаях. В нашем случае Рубинсон пишет: «Соответствие города детали представляет собой множество фактов, которое существует независимо от того, знаем ли мы, какие города соответствуют каким фактам. В SQL запросы всегда подразумевают знание подобной взаимосвязи, а не просто ее существование».

Назад к Дж. Булю

В некоторых системах SQL имеются дополнительные предикаты сравнения с более интуитивным поведением при работе с NULL-значениями: например, булев предикат X<=>Y в MySQL истинен, когда оба аргумента равны NULL, и ложен, когда ровно один равен NULL; следовательно, результат сравнения никогда не будет UNKNOWN.

Для ясности напомним, что третьим логическим значением (наряду с TRUE и FALSE) логики SQL является UNKNOWN, а не NULL. Маркер неопределенных значений NULL служит лишь средством генерации трехзначных высказываний (условий).

Рассмотрим первую часть запроса Дейта: «Выдать пары SNO-PNO, для которых поставщик и деталь располагаются в разных городах». Двузначная логика здесь подразумевает, что города, в которых располагается поставщик и деталь, либо различны, либо совпадают. В трехзначной логической системе SQL нам это может быть просто неизвестно. Аналогично обстоит дело со второй частью запроса: «Выдать пары SNO-PNO, для которых город, в котором располагается деталь, не Париж». И здесь неопределенное

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×