Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Базы Данных - Сибилев, 2007

.pdf
Скачиваний:
290
Добавлен:
11.05.2015
Размер:
1.93 Mб
Скачать

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 Ограничений на число столбцов таблицы, производимой подзапросом, нет в обоих стандартах языка.