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

Учебное пособие 800353

.pdf
Скачиваний:
1
Добавлен:
01.05.2022
Размер:
1.88 Mб
Скачать

предложениях SQL в прикладной программе), поскольку смысл знака «*» может измениться, если для этой программы перегенерируется план прикладной задачи, а в данном промежутке времени к рассматриваемой таблице был добавлен другой столбец. В этом пособии «SELECT *» будет использоваться только в таких контекстах, где так делать безопасно (в основном только в интерактивных контекстах), и фактическим пользователям рекомендуется поступать подобным образом.

Отметим, наконец, что «*» может уточняться именем соответствующей таблицы. Допустима, например, следующая форма записи:

SELECT S.* FROM S;

Ограниченная выборка

Выдать номера поставщиков, которые находятся в Париже и имеют состояние большее, чем 20:

SELECT НОМЕР_ПОСТАВЩИКА

FROM S

WHERE ГОРОД = ’Париж’ AND СОСТОЯНИЕ > 20;

Результат:

НОМЕР_ПОСТАВЩИКА

S3

Условие, или предикат, следующий за ключевым словом WHERE, может включать операторы сравнения =, != (неравно), >, >=, <, и <=, булевские операторы AND (и), OR (или) и NOT (нет), а скобки указывают требуемый порядок вычислений. В таком предикате числа сравниваются алгебраически — отрицательные числа считаются меньшими, чем положительные, независимо от их абсолютной величины. Строки литер сравниваются в соответствии с их представлением в коде ASCII. Если нужно сравнить две строки литер, имеющих разные длины, более короткая строка

250

концептуально дополняется справа пробелами для того, чтобы обе строки имели одинаковую длину перед тем, как будет осуществляться их сравнение.

Выборка с упорядочением

Выдать номера и состояния поставщиков, находящихся в Париже, в порядке убывания их состояния:

SELECT НОМЕР_ПОСТАВЩИКА, СОСТОЯНИЕ

FROM S

WHERE ГОРОД = ’Париж’

ORDER BY СОСТОЯНИЕ DESC;

Результат:

 

НОМЕР_ПОСТАВЩИКА

СОСТОЯНИЕ

S3

30

S2

10

В общем случае не гарантируется, что результирующая таблица будет упорядочена каким-либо определенным образом. Здесь, однако, пользователь специфицировал, что результат перед тем, как он будет показан, должен быть организован в определенной последовательности. Упорядочение может быть специфицировано таким же образом, как в предложении CREATE INDEX:

имя—столбца [упорядочение] [, имя—столбца [упорядочение]] ...,

где «упорядочение», как и ранее, это ASC (возрастание) или DECS (убывание), и по умолчанию принимается ASC. Каждое «имя—столбца» должно идентифицировать некоторый столбец результирующей таблицы. Поэтому, например, следующее предложение недопустимо:

SELECT НОМЕР_ПОСТАВЩИКА

FROM S

ORDER BY ГОРОД;

Разрешается также идентифицировать столбцы во фразе ORDER BY (упорядочить по) «номерами—столбцов» вместо «имен—столбцов», где «номер—столбца» указывает

251

порядковую позицию (слева направо) данного столбца в результирующей таблице запроса. Благодаря этому возможно упорядочение результата на основе «вычисляемых столбцов», которые не обладают именем. Например, упорядочить результат по возрастанию номера детали в рамках возрастания веса в граммах:

SELECT НОМЕР_ДЕТАЛИ, ВЕС*454

FROM P

ORDER BY 2, НОМЕР_ДЕТАЛИ; [или ORDER BY 2,1;]

Здесь «2» ссылается на второй столбец результирующей таблицы.

Получаем:

НОМЕР_ДЕТАЛИ

P1

5448

P5

5448

P4

6356

P2

7718

P3

7718

P6

8626

Выборка с использованием between (между)

Выдать сведения о деталях, вес которых находится в диапазоне от 16 до 19 включительно:

SELECT НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ЦВЕТ, ВЕС,

ГОРОД

 

 

 

 

FROM P

 

 

 

WHERE ВЕС BETWEEN 16 AND 19;

 

 

Имеем следующий результат:

 

 

 

НОМЕР_

НАЗВАНИЕ

ЦВЕТ

ВЕС

ГОРОД

ДЕТАЛИ

 

 

 

 

P2

Болт

З

17

Париж

 

 

еленый

 

 

P3

Винт

Голубой

17

Рим

P6

Блюм

Красный

19

Лондон

Может быть также специфицировано NOT BETWEEN (не при252

надлежит диапазону между), например:

SELECT НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ЦВЕТ, ВЕС, ГОРОД

FROM P

WHERE ВЕС NOT BETWEEN 16 AND 19;

Получаем тогда:

 

 

 

НОМЕР_

НАЗВАНИЕ

ЦВЕТ

ВЕС

ГОРОД

ДЕТАЛИ

 

 

 

 

P1

Гайка

Красный

12

Лондон

P4

Винт

Красный

14

Лондон

P5

Кулачок

Голубой

12

Париж

Выборка с использованием in (принадлежит)

Выдать детали, вес которых равен 12, 16 или 17:

SELECT НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ЦВЕТ, ВЕС, ГОРОД

FROM Р

WHERE ВЕС IN (12, 16, 17);

Результат:

 

 

 

 

НОМЕР_

НАЗВАНИЕ

ЦВЕТ

ВЕС

ГОРОД

ДЕТАЛИ

 

 

 

 

P1

Гайка

Красный

12

Лондон

P2

Болт

Зеленый

17

Париж

P3

Винт

Голубой

17

Рим

P5

Кулачок

Голубой

12

Париж

Предикат IN является в действительности просто краткой записью предиката, представляющего собой последовательность отдельных сравнений, соединенных операторами OR (или). Предыдущее предложение SELECT эквивалентно следующему:

SELECT НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ЦВЕТ, ВЕС, ГОРОД

FROM Р WHERE ВЕС = 12 OR ВЕС = 16

253

OR ВЕС = 17;

Имеется в распоряжении также предикат NOT IN (не принадлежит), например предложение;

SELECT НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ЦВЕТ, ВЕС, ГОРОД

FROM P

WHERE ВЕС NOT IN (12, 16, 17);

дает результат;

 

 

 

 

НОМЕР_

НАЗВАНИЕ

ЦВЕТ

ВЕС

ГОРОД

ДЕТАЛИ

 

 

 

 

P4

Винт

Красный

14

Лондон

P6

Блюм

Красный

19

Лондон

Подобно предикату IN предикат NOT IN может рассматриваться только как сокращенная запись другого предиката, который не использует NOT IN. Упражнение. Запишите «развернутую форму» предложения из предшествующего примера.

Выборка с использованием предиката like (похоже на)

Выдать все детали, названия которых начинаются с буквы «С»:

SELECT НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ЦВЕТ, ВЕС, ГОРОД

FROM P

WHERE НАЗВАНИЕ LIKE ’С%’;

Получаем результат:

НОМЕР_

НАЗВАНИЕ

ЦВЕТ

ВЕ

ГОРОД

ДЕТАЛИ

 

 

С

 

P5

Кулачок (Cam)

Голубой

12

Париж

P6

Блюм (Cog)

Красный

19

Лондон

Обычно предикат LIKE имеет форму:

 

 

имя—столбца LIKE литерная—строковая—константа,

где «имя—столбца» должно обозначать столбец типа CHAR

или VARCHAR. Этот предикат

принимает для заданной

 

254

 

 

 

будет принимать значение истина, если АДРЕС содержит где-либо внутри него строку ’Беркли’ будет принимать
значение истина, если значение в столбце НОМЕР_ПОСТАВ ЩИКА состоит в точности из трех литер и первая из них литера «S» будет принимать значение истина, если значение в столбце

записи значение истина, если значение в указанном столбце соответствует образцу, специфицируемому «литерной— строковой—константой». Литеры этой константы интерпретируются следующим образом:

-Литера «_» (разрыв или подчеркивание) обозначает любую одиночную литеру.

-Литера «%» (процент) обозначает любую последовательность из n литер (где n может быть нулем).

-Все другие литеры обозначают просто сами себя.

Следовательно, в приведенном примере предложение SELECT будет осуществлять выборку записей из таблицы P, для которых значение в столбце НАЗВАНИЕ начинается буквой «С» и содержит любую последовательность из нуля или более литер, следующую за этой буквой «С».

Ниже приведено еще несколько примеров, в которых используется LIKE:

АДРЕС LIKE ’% Беркли %’

НОМЕР_ПОСТАВЩИКА LIKE ’S__’

НАЗВАНИЕ LIKE ’% К___’

255

НАЗВАНИЕ состоит из четырех или более литер и трем последним из них предшествует литера «К»

ГОРОД NOT LIKE ’% Е %’ будет принимать значение истина, если значение ГОРОД не содержит литеры

«Е»

Выборка, при которой вовлекается null (неопределенное значение)

Допустим, например, что значением в столбце СОСТОЯНИЕ для поставщика S5 является не 30, а неопределенное значение. Выдать номера поставщиков, у которых состояние больше, чем 25:

SELECT НОМЕР_ПОСТАВЩИКА

FROM S

WHERE СОСТОЯНИЕ > 25;

Врезультате получим:

НОМЕР_ПОСТАВЩИКА

S3

Здесь поставщик S5 не был назван в результате. Если неопределенное значение сравнивается с некоторым другим значением при вычислении предиката, то независимо от используемого оператора сравнения результатом сравнения никогда не является истина, даже если этот другой операнд также является неопределенным значением. Иными словами, если оказывается, что СОСТОЯНИЕ имеет неопределенное значение, то ни одно из следующих сравнений не будет принимать значение истина:

СОСТОЯНИЕ > 25

256

СОСТОЯНИЕ < = 25 СОСТОЯНИЕ = 25 СОСТОЯНИЕ !=25 СОСТОЯНИЕ =

NULL (Это недопустимая синтаксическая конструкция. См. ниже)

СОСТОЯНИЕ != NULL (Это—тоже).

Поэтому если издать запрос:

SELECT НОМЕР_ПОСТАВЩИКА

FROM S

WHERE СОСТОЯНИЕ < = 25;

и сравнить его результат с результатом предыдущего запроса, то можно установить, что поставщик S5 не появляется ни в одном из них. Результат приведенного запроса:

НОМЕР_ПОСТАВЩИКА

S1

S2

S4

Для проверки наличия (или отсутствия) неопределенного значения предусмотрен специальный предикат вида:

имя — столбца IS [NOT] NULL

Например:

SELECT НОМЕР_ПОСТАВЩИКА

FROM S

WHERE СОСТОЯНИЕ IS NULL;

Врезультате имеем:

НОМЕР_ПОСТАВЩИКА

S5

Синтаксическая конструкция «СОСТОЯНИЕ = NULL» является некорректной, поскольку ничто — и даже само неопределенное значение — не считается равным неопределенному значению. (Несмотря на это, два неопределенных значения рассматриваются, однако, как дубликаты друг друга при исключении дубликатов. Предложение SELECT DISTINCT (ВЫБРАТЬ РАЗЛИЧНЫЕ)

257

даст в результате не более одного неопределенного значения. Аналогичным образом индекс со спецификацией UNIQUE (уникальный) будет допускать в индексируемом столбце не более одного неопределенного значения. Наконец, при упорядочении ORDER BY (УПОРЯДОЧИТЬ ПО) неопределенные значения интерпретируются, как будто бы они больше или равны всем значениям, не являющимся неопределенными).

Заметим, между прочим, что использование символа NULL во фразе SELECT не допускается. Например, следующая конструкция некорректна:

SELECT НОМЕР_ДЕТАЛИ, ’ВЕС = ’, NULL FROM P

WHERE ВЕС IS NULL;

Запросы, использующие соединение

Способность «соединять» две или более таблицы в одну представляет собой одну из наиболее мощных возможностей реляционных систем. Фактически наличие операции соединения (join) — едва ли не самое главное, что отличает реляционные системы от систем других типов. Итак, что такое соединение? Говоря нестрого, это запрос, в котором выборка данных осуществляется более чем из одной таблицы. Ниже приводится простой пример.

Простое эквисоединение

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

SELECT S.*, P.* FROM S, Р

WHERE S.ГОРОД = Р.ГОРОД;

Заметим, что здесь ссылки на поля во фразе WHERE

258

должны уточняться именами содержащих их таблиц. В результате получим следующую ниже таблицу 50. (Во избежание двусмысленности в этой таблице два столбца ГОРОД показаны явным образом как S.ГOPOД и Р.ГОРОД.)

Таблица 50

НОМЕР_

ФА

СОСТОЯ S.ГОРОД

ПОСТАВЩИКА

МИЛИЯ

НИЕ

 

 

S1

 

Смит

20

Лондон

S1

 

Смит

20

Лондон

S1

 

Смит

20

Лондон

S2

 

Джонс

10

Париж

S2

 

Джонс

10

Париж

S3

 

Блейк

30

Париж

S3

 

Блейк

30

Париж

S4

 

Кларк

20

Лондон

S4

 

Кларк

20

Лондон

S4

 

Кларк

20

Лондон

 

 

 

Продолжение таблицы 50

НОМЕР_

НАЗВА

ЦВЕТ

ВЕС

P.ГОРОД

ДЕТАЛИ

НИЕ

 

 

 

 

P1

Гайка

Красный

12

Лондон

P4

Винт

Красный

14

Лондон

P6

Блюм

Красный

19

Лондон

P2

Болт

Зеленый

17

Париж

P5

Кулачо

Голубой

12

Париж

 

к

 

 

 

 

P2

Болт

Зеленый

17

Париж

P5

Кулачо

Голубой

12

Париж

 

к

 

 

 

 

P1

Гайка

Красный

12

Лондон

P4

Винт

Красный

14

Лондон

P6

Блюм

Красный

19

Лондон

Пояснение. Из формулировки задачи на естественном языке ясно, что требуемые данные можно получить из двух

259