Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Белобжеский_Лекции_по_ББД.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
5.5 Mб
Скачать

Запрос нескольких таблиц

В этом разделе мы распространим наше обсуждение языка SQL на операции с дву­мя и более таблицами. Для иллюстрации этих команд будут использоваться таб­лицы СТУДЕНТ, ЗАНЯТИЯ и ЗАПИСЬ.

Вложенные запросы

Предположим, мы хотим знать имена студентов, записанных на предмет под шифром BD445. Если нам известно, что на этот предмет записаны студенты с но­мерами 100 и 200, то правильные результаты выдаст следующий запрос:

SELECT Имя

FROM СТУДЕНТ

WHERE ЛичныйНомер IN [100, 200]

Обычно мы не знаем номеров студентов, записанных на какой-то предмет, но у нас есть возможность их определить. Рассмотрим выражение

SELECT НомерСтудента

FROM ЗАПИСЬ

Результатом операции будет таблица:

WHERE НазваниеПредмета = 'BD445'

Вот те номера студентов, которые нам требовались. Комбинируя последние два запроса, мы получаем следующее:

SELECT Имя

FROM СТУДЕНТ

WHERE ЛичныйНомер IN

(SELECT НомерСтудента

FROM ЗАПИСЬ

WHERE НазваниеПредмета = 'BD445')

Второе предложение SELECT, которое называется вложенным запросом (subquery), заключено в круглые скобки.

Эти выражения оказывается проще понять, если читать их снизу вверх. По­следние три оператора выдают номера студентов, записанных на предмет BD445, а первые три оператора выдают имена выбранных студентов. Результат запроса таков:

Чтобы данная операция была семантически корректной, СТУДЕНТ.ЛичныйНомер и ЗАПИСЬ.НомерСтудента должны иметь один и тот же домен.

Вложенные запросы могут состоять из трех или даже большего количества таблиц. Предположим, например, что мы хотим узнать имена студентов, в распи­сании у которых стоят занятия по понедельникам, средам и пятницам с 3 часов (они обозначены в наших данных как 'ПСЯЗ'). Прежде всего 4нам нужны назва­ния предметов, занятия по которым начинаются в это время:

SELECT ЗАНЯТИЯ.НазваниеПредмета

FROM ЗАНЯТИЯ

WHERE Время = 'ПСЯЗ'

(Поскольку мы имеем дело с тремя различными таблицами, мы указываем имена столбцов вместе с именами таблиц, чтобы избежать недоразумений и не­однозначности. Так, ЗАНЯТИЯ.НазваниеПредмета обозначает столбец НазваниеПред­мета в отношении ЗАНЯТИЯ.)

Далее мы определяем личные номера студентов, записанных на эти предме­ты, с помощью следующего выражения:

SELECT ЗАПИСЬ.НомерСтудента

FROM ЗАПИСЬ

WHERE ЗАПИСЬ.НазваниеПредмета IN

(SELECT ЗАНЯТИЯ.НазваниеПредмета

FROM ЗАНЯТИЯ

WHERE Время = 'ПСЯЗ')

Это даст результат:

то есть номера студентов, занимающихся в указанное нами время. Чтобы полу­чить имена этих студентов, мы используем следующее выражение:

SELECT СТУДЕНТ.Имя

FROM СТУДЕНТ

WHERE СТУДЕНТ.ЛичныйНомер IN

SELECT ЗАПИСЬ.НомерСтудента

FROM ЗАПИСЬ

WHERE ЗАПИСЬ.НазваниеПредмета IN

(SELECT ЗАНЯТИЯ.НазваниеПредмета

FROM ЗАНЯТИЯ

WHERE ЗАНЯТИЯ.Время = 'ПСЯЗ')

Результатом будет:

Эта стратегия работает хорошо, пока атрибуты, входящие в ответ, происходят из одной и той же таблицы. Если же результат содержит информацию из двух или более таблиц, перед нами встает проблема. Предположим, к примеру, что мы хотим узнать имена студентов и названия предметов, на которые они записаны. То есть нам нужны атрибуты ЛичныйНомер, ИмяСтудента и НазваниеПредмета. В этом случае результаты происходят из двух различных таблиц (СТУДЕНТ и ЗАПИСЬ), и стратегия вложенных запросов не работает.