К сожалению в стандартном SQL нет предикатов типа CONTAINS и CONTAINED, которые проверяют вхождение множества во множество. С помощью этих предикатов можно было бы довольно легко выражать запросы, эквивалентные использованию предикатов общности в реляционном исчислении или операции деления в реляционной алгебре.
В связи с этим запросы, требующие квантора общности, выражаются с использованием других возможностей. Смысл этих замен заключается в следующем. Вспомним, что ограниченный квантор общности выражается в исчислении предикатов следующим образом:
"х(Р(х) É Q(x,y)
Взяв двойное отрицание от этого выражения и выразив импликацию через дизъюнкцию, мы получим:
Ø$х(Р(х) & ØQ(x,y))
Таким образом, квантор всеобщности выражается через отрицания и квантор существования.
Рассмотрим пример. Пусть следует дать ответ на следующий запрос: "Выдать преподавателей, читающих все типы лекций". Этот запрос может быть переформулирован следующим образом: "Выдать преподавателей, для которых НЕ СУЩЕСТВУЕТ таких типов лекций, которые они НЕ читают". Первая часть этого переформулированного запроса ("Выдать преподавателей, для которых НЕ СУЩЕСТВУЕТ таких типов лекций, которые...") выражается следующим образом:
SELECT t.Name
FROM TEACHER t
WHERE NOT EXISTS (SELECT l.Type
FROM LECTURE l
WHERE ...
)
Теперь следует выразить записать выражение, которое определяет условие на тип лекции. Для этого сначала выразим следующий вспомогательный запрос: "Выдать такие типы лекций, которые не читает преподаватель Иванов", имеющий, в принципе, тот же вид, что и в исходном запросе за исключением того, здесь указывается конкретный преподаватель. Он имеет следующий вид:
SELECT l.Type
FROM LECTURE l
WHERE NOT EXISTS (SELECT *
FROM TEACHER t2
WHERE t2.#T = l.#T AND t2.Name = "Иванов"
Теперь этот второй запрос можно подставить в первый в следующем виде:
· фраза WHERE второго запроса заменяет фразу WHERE вложенного подзапроса первого запроса.
· во фразе WHERE второго запросе вместо константы конкретного имени преподавателя (Иванов) используется имя преподавателя, определяемое переменной первого запроса (t.name). В результате получим: