
Базы Данных - Сибилев, 2007
.pdf
171
SELECT DISTINCT Snam, St
FROM S;
Использованное здесь ключевое слово DISTINCT сообщит системе,
что для завершения работы над запросом она должна выполнить ещё один шаг:
Шаг 5. Исключить дубликаты строк из временной таблицы, создан-
ной на шаге 4.
Замечание. На практике это может привести к потере информации.
Так, в нашем примере существует два различных поставщика с одинако-
выми именами и статусами. Удалив дубликат строки из выходной табли-
цы, мы утеряем информацию об одном из них.
Мы можем получить более приятную для глаза русского человека
таблицу, если запишем оператор выборки так:
SELECT DISTINCT Snam AS Имя, St AS Статус
FROM S;
В этом случае формирование выходной таблицы завершится сле-
дующим шагом:
Шаг 5. Во временной таблице, созданной шагом 5, изменить имена
столбцов Snam и St на Имя и Статус соответственно.
Вот выходная таблица, построенная этим оператором:
Имя |
Статус |
Владимир |
30 |
Григорий |
80 |
Иван |
100 |
Константин |
100 |
|
|
Николай |
50 |
Петр |
20 |
Егор |
100 |
Сергей |
90 |
Пример 2. Получить номера и наименования всех деталей и их веса в килограммах.
SELECT Pnum, Pnam, We/1000
FROM P;

172
Этот оператор реализует реляционную операцию расширения схемы
[2, с.82]. Шаги 1 и 2 процедуры обработки этого запроса аналогичны опи-
саным выше. На следующем шаге будет сформирована новая временная таблица, содержащая неименованный столбец, принимающий значения выражения We/1000. Затем система выполнит SQL-проекцию этой табли-
цы на столбцы Pnum, Pnam и дополнительный неименованный столбец.
Результат приведён ниже.
Pnum |
Pnam |
|
P1 |
корпус |
0,3 |
P2 |
разъём |
0,003 |
P3 |
кнопка |
0,005 |
P4 |
корпус |
0,8 |
P5 |
панель |
0,1 |
P6 |
кинескоп |
1,2 |
P7 |
кнопка |
0,01 |
P8 |
панель |
0,45 |
P9 |
лампочка |
0,001 |
Следующий оператор произведёт более наглядную таблицу.
SELECT Pnum AS Номер,
Pnam AS Наименование,
We/1000 AS Вес, 'кг' AS Ед. измер.
FROM P;
При обработке предложения SELECT этого оператора временная таблица, построенная предложением FROM, будет дополнена двумя име-
нованными столбцами. Они будут принимать значения выражений, одно из которых является символьной константой. Выходная таблица запроса имеет вид:
Номер |
Наименование |
Вес |
Ед. измер. |
P1 |
корпус |
0,3 |
кг |
P2 |
разъём |
0,003 |
кг |
|
|
|
|
P3 |
кнопка |
0,005 |
кг |
|
|
|
|
P4 |
корпус |
0,8 |
кг |
P5 |
панель |
0,1 |
кг |
P6 |
кинескоп |
1,2 |
кг |

|
|
173 |
|
|
|
|
|
|
|
P7 |
кнопка |
|
0,01 |
кг |
P8 |
панель |
|
0,45 |
кг |
P9 |
лампочка |
|
0,001 |
кг |
|
|
|
|
|
Если источником данных является одна базовая таблица, обязатель-
ные предложения оператора SELECT могут указывать лишь на две опера-
ции – расширения схемы и SQL-проекции.
7.2.6 Предикаты SQL
Предикаты используются в предложениях WHERE и HAVING опе-
ратора SELECT для определения условий, которым должны удовлетво-
рять выбираемые строки F- или G-таблицы. Кроме того, в операторах об-
новления данных они указывают область действия, а в операторах опреде-
ления объектов задают ограничения на вводимые значения данных.
предикат ::= [(] [NOT] элементарный_предикат
[{AND | OR} предикат ] [)] [IS [NOT] 3VL-значение]
элементарный_предикат ::= предикат_comparision | предикат_between
| предикат_in | предикат_like | предикат_null
| предикат_quantifired_comparision | предикат_exists
| предикат_unique | предикат_match
| предикат_overlap
3VL-значение ::= TRUE | FALSE | UNKNOWN
SQL использует трёхзначную логику (3VL). Это обусловлено тем,
что допускаются неопределённые (NULL) значения столбцов. NULL-
значения могут появляться в строках производных таблиц в результате выполнения некоторых операций, например, внешних соединений. Эти значения могут участвовать в операциях сравнения. Поскольку невозмож-
но сказать что-либо определённое о результате сравнения с участием
NULL, приходится наряду с TRUE (истина) и FALSE (ложь) вводить ещё

174
одно возможное значение результата сравнения – UNKNOWN (неизвест-
но) – и определять исчисление высказываний на трёхзначном множестве.
Предикаты SQL могут принимать значения TRUE, FALSE или
UNKNOWN.
Предикаты могут быть операндами булевых операторов AND, OR,
NOT, а также SQL-оператора IS. Ниже приведены таблицы истинности для этих операторов.
Таблицы истинности операторов 3VL
X |
NOT X |
|
|
TRUE |
FALSE |
|
|
FALSE |
TRUE |
|
|
UNKNOWN |
UNKNOWN |
|
|
AND |
TRUE |
FALSE |
UNKNOWN |
|
|
|
|
TRUE |
TRUE |
FALSE |
UNKNOWN |
|
|
|
|
FALSE |
FALSE |
FALSE |
FALSE |
|
|
|
|
UNKNOWN |
UNKNOWN |
FALSE |
UNKNOWN |
|
|
|
|
OR |
TRUE |
|
FALSE |
|
UNKNOWN |
|
|
|
|
|
|
|
|
TRUE |
TRUE |
|
TRUE |
|
TRUE |
|
|
|
|
|
|
|
|
FALSE |
TRUE |
|
FALSE |
|
UNKNOWN |
|
|
|
|
|
|
|
|
UNKNOWN |
TRUE |
|
UNKNOWN |
UNKNOWN |
||
|
|
|
|
|
|
|
|
|
|
|
|
||
IS |
TRUE |
FALSE |
UNKNOWN |
|
||
|
|
|
|
|
|
|
TRUE |
TRUE |
FALSE |
FALSE |
|
||
|
|
|
|
|
|
|
FALSE |
FALSE |
TRUE |
FALSE |
|
||
|
|
|
|
|
||
UNKNOWN |
FALSE |
FALSE |
TRUE |
|
||
|
|
|
|
|
|
|
Рассмотрим теперь элементарные предикаты. Многие из них сравни-
вают множества значений, а потому используют так называемые конст-
рукторы значений строк – заключённые в круглые скобки списки выраже-
ний для вычисления значений. Однако для простоты мы здесь будем изла-
гать определения в духе стандарта SQL1, допускающего сравнения только отдельных значений. Кроме того, мы обсудим здесь не все перечисленные

175
выше предикаты, а только важнейшие из них. Полные определения преди-
катов SQL2 можно найти в [4].
Предикаты сравнения сравнивают два значения15.
предикат_comparision ::=
выражение оператор_сравнения выражение
Здесь выражение есть любое допустимое выражение для вычисления зна-
чения.
оператор_сравнения ::= = | < | > | <= | >= | <>
Выражения должны производить сравнимые, т.е. принадлежащие со-
вместимым типам данных, значения. Если хотя бы одно из них приняло значение NULL, то любой предикат сравнения примет значение
UNKNOWN.
Например, предикат X <> Y примет значение TRUE для X и Y, рав-
ных ‘Томск’ и ‘Яя’ соответственно. Однако сравнение NULL <> NULL
даст результат UNKNOWN, несмотря на то, что никакие два NULL-
значения не совпадают.
Предикат BETWEEN проверяет, попадает ли значение в заданную область.
предикат_between ::=
выражение [NOT] BETWEEN выражение AND выражение
Предикат
exp1 BETWEEN exp2 AND exp3
равносилен предикату
exp1 >= exp2 AND exp1 <= exp3.
Значения предиката в зависимости от значений проверяемого выра-
жения и границ диапазона нетрудно найти по таблицам истинности 3VL.
Примеры:
ПРЕДИКАТ ЗНАЧЕНИЕ
15 Строго говоря, два множества значений, возможно, одноэлементных.

176 |
|
|
5 BETWEEN 3 AND 8 |
|
TRUE |
|
||
|
|
|
5 BETWEEN 6 AND NULL |
|
FALSE |
|
|
|
5 BETWEEN NULL AND 8 |
|
UNKNOWN |
|
|
|
Предикат IN проверяет, принадлежит ли значение заданному мно-
жеству значений.
предикат_in ::= выражение [NOT] IN (выражение.,..) | подзапрос
В этой синтаксической форме подзапрос производит таблицу с един-
ственным столбцом16.
Предикат выполняет сравнения значения выражения с каждым зна-
чением столбца (списка) в соответствии с определением оператора эквива-
лентности. Результатом всех сравнений является одно истинностное зна-
чение. Следующие два предиката равносильны.
exp IN (exp1, exp2,…, expN);
exp = exp1 OR exp = exp2 OR … OR exp = expN.
Примеры: |
|
|
||
|
ПРЕДИКАТ |
|
ЗНАЧЕНИЕ |
|
|
|
|||
|
|
|
|
|
5 |
IN (3, 5, 2) |
|
TRUE |
|
|
|
|
|
|
5 |
IN (3, 7, 2) |
|
FALSE |
|
|
|
|
|
|
5 |
IN (3, NULL, 2) |
|
UNKNOWN |
|
|
|
|
|
|
5 |
IN (NULL, 5, NULL) |
|
TRUE |
|
|
|
|
|
|
Предикат LIKE работает только со строками символов. Он прове-
ряет, входит ли заданная подстрока в состав другой строки.
предикат_like ::=
выражение_для_вычисления_строки [NOT] LIKE
выражение_для_вычисления_строки [ESCAPE
символ]
16 Это ограничение SQL1. Определение SQL2 его не содержит.
177
Второе выражение производит т.н. шаблон или образец – символь-
ную строку, которая отыскивается в значении первого выражения.
В простейшем случае предикат LIKE аналогичен предикату сравне-
ния для символьных строк, но не совпадает с ним полностью. Предикат сравнения автоматически дополняет более короткую строку концевыми пробелами до выравнивания длин сравниваемых строк. Предикат LIKE
этого не делает. Поэтому, например, значения первого и второго из ниже-
приведённых предикатов – TRUE, а значение третьего – FALSE.
‘Томск’ = ‘Томск ’; ‘Томск’ LIKE ‘Томск’; ‘Томск ’ LIKE ‘Томск’.
В общем случае образец может содержать знаки шаблона (трафа-
ретные символы):
− символ подчёркивания ‘_’ заменяет любой один символ в прове-
ряемом значении;
− символ процента ‘%’ заменяет подстроку символов любой (в том числе и нулевой) длины.
При использовании знаков шаблона предикат отыскивает в прове-
ряемом значении подстроки, явно указанные в шаблоне. Например, сле-
дующие предикаты принимают значение TRUE:
‘Томск’ LIKE ‘_омск’; ‘Омск’ LIKE ‘%омск’; ‘Атомск’ LIKE
‘%омск’.
Однако предикат ‘омск’ LIKE ‘_омск’ имеет значение FALSE.
Если поисковая подстрока включает символы ‘_’ или ‘%’ как лите-
ралы, то действие их как знаков шаблона следует отменить. Для этого нужно определить управляющий символ с помощью предложения ESCAPE
и включить его в поисковую строку перед тем символом шаблона, который должен трактоваться как литерал.
Пример. Предикат X LIKE ‘__|% %’ ESCAPE ‘|’ примет значение
TRUE на любой последовательности символов X, начинающейся двумя
178
любыми символами, имеющей в третьей позиции символ ‘%’, в четвёртой
– пробел, а далее – всё, что угодно, в том числе и ничего. Символ ‘%’ в
первом вхождении рассматривается как литерал, поскольку перед ним по-
мещён управляющий символ ‘|’, а во втором – как знак шаблона.
Предикат LIKE принимает истинностные значения в соответствии со следующими правилами.
−Если проверяемое значение или образец, или управляющий символ есть NULL, то значение предиката UNKNOWN.
−В противном случае, если проверяемое значение и образец эквива-
лентны в смысле определения предиката сравнения, то значение предика-
та TRUE.
− В противном случае, если в проверяемом значении можно выде-
лить сегменты, эквивалентные явно заданным подстрокам образца, и сег-
менты, соответствующие знакам шаблона, и эти сегменты расположены в проверяемом значении и в образце в одинаковой последовательности, то значение предиката TRUE.
− Если не выполнено ни одно из перечисленных условий, то значе-
ние предиката FALSE.
В нашем примере «истинными» будут признаны строки: '55% белков’; '30% жиров'; '05% углеводов',
а «ложными» – строки:
'содержит 55% белков’; '30%жиров'; '5% углеводов'.
Предикат NULL предназначен для обнаружения и обработки неоп-
ределённых значений. Значения NULL невозможно локализовать с помо-
щью предиката сравнения, так как любое сравнение с участием NULL да-
ёт результат UNKNOWN. Поэтому значение предиката X = NULL не зави-
сит от значения X. Если необходимо найти неопределённое значение столбца, то следует использовать конструкцию
предикат_null ::= выражение IS [NOT] NULL

179
Предикат X IS NULL примет значение TRUE, если значение X не определено и FALSE – в противном случае. Значение UNKNOWN невоз-
можно.
Предикат QUANTIFIRED COMPARISION является специальным
типом предиката (квантифицированного) сравнения.
предикат_quantifired_comparision ::=
выражение оператор_сравнения
{ALL | ANY | SOME} подзапрос
Здесь подзапрос производит таблицу с единственным столбцом.17
Ключевые слова (кванторы) ANY и SOME – синонимы. Для SOME спра-
ведливо то и только то, что будет сказано далее об ANY.
Предикат выполняет сравнения значения выражения со значениями столбца в соответствии с определением оператора сравнения. Результатом всех сравнений является одно истинностное значение. Оно зависит от ис-
пользованного квантора. Если подзапрос производит непустую таблицу,
содержащую N строк, то следующие пары предикатов равносильны. exp θ ALL подзапрос;
exp θ val1 AND exp θ val2 AND … AND exp θ valN. exp θ ANY (подзапрос);
exp θ val1 OR exp θ val2 OR … OR exp θ valN.
Здесь valJ есть J-тая строка таблицы, произведённой подзапросом
(значение столбца), а символом θ обозначен оператор сравнения.
Если подзапрос производит пустую таблицу, то предикат с кванто-
ром ALL примет значение TRUE, а с квантором ANY – значение FALSE
независимо от использованного оператора сравнения.
Примеры. В предикатах, приведённых ниже, в скобках указаны не подзапросы, а их результаты. Мы используем это отклонение от синтакси-
са для пояснения смысла конструкции.
17 Это ограничение SQL1. Определение SQL2 его не содержит.

|
180 |
|
|
ПРЕДИКАТ |
|
ЗНАЧЕНИЕ |
|
|
|||
|
|
|
|
5 |
>= ALL (3, 5, 2) |
|
TRUE |
|
|
|
|
5 |
> ALL (3, 5, 2) |
|
FALSE |
|
|
|
|
5 |
>= ALL (3, NULL, 2) |
|
UNKNOWN |
|
|
|
|
5 |
> ANY (3, 5, 2) |
|
TRUE |
|
|
|
|
5 |
< ANY (3, 5, 2) |
|
FALSE |
|
|
|
|
5 |
>= ANY (3, NULL, 2) |
|
TRUE |
|
|
|
|
5 |
>= ANY (6, NULL, 9) |
|
UNKNOWN |
|
|
|
|
Предикат EXISTS предназначен для проверки наличия строк в таб-
лице, произведенной запросом.
предикат_exists ::= EXISTS подзапрос18
Возможны лишь два значения этого предиката:
−TRUE, если таблица, произведённая подзапросом, содержит хотя бы одну строку;
−FALSE в противном случае.
Предикат реализует квантор существования реляционного исчисле-
ния с переменными-кортежами. Проблемы его использования и примеры обсуждаются ниже в п. 7.2.12.
Мы познакомились здесь не со всеми перечисленными в начале раз-
дела предикатами, а только с важнейшими из них. Приведённые определе-
ния соответствуют стандарту SQL1. Стандарт SQL2 включает их как часть.
Полные определения предикатов SQL2 можно найти в [4].
Продолжим теперь обсуждение предложений оператора SELECT.
7.2.7 Предложение WHERE
Предложение
WHERE предикат
реализует операцию селекции или ограничения по условию [2, с. 74]. Опе-
рандом является F-таблица, построенная предложением FROM.
18 Ограничений на число столбцов таблицы, производимой подзапросом, нет в обоих стандартах языка.