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

Лекция 12 Язык структурных запросов sql (продолжение) Соединение

В SQL реализуются различные варианты эквисоединения. Известно, что с помощью переименования и эквисоединения можно реализовать естественное соединение. Но в SQL к переименованию прибегать не обязательно: допускается именование атрибута с указанием имени таблицы, к которой он относится. Таким образом, можно обеспечить уникальность имен даже в случае непустого пересечения схем соединяемых отношений. Соответствующая конструкция – <имя таблицы>.<имя атрибута>.

Остановимся на единственном варианте эквисоединения, отвечающем оператору реляционной алгебры, различные варианты Join рассматривать не будем. Напомним, что этот оператор записывается как r[A1 = B1, A2 = B2,…, Am = Bm]s, где r и s – соединяемые отношения, а A1, A2,…, Am и B1, B2,…, Bm – атрибуты, по равенству которых производится соединение. В SQL соответствующий оператор выглядит так:

Select <список атрибутов> From r, s

Where A1 = B1 and A2 = B2 and and Am = Bm;

Вместо знака равенства может стоять знак любой операции сравнения, лишь бы она была определена на соответствующих доменах. В этом случае говорим о -соединении.

Рассматриваемый вид соединения основан на ссылочной целостности. Если для какого-либо значения одного из сравниваемых атрибута нет равного ему значения второго, запись в выборку не включается. Таким образом, если рассматривать один из атрибутов как родительский ключ, а другой как внешний, ссылающийся на него, необходимым условием включения записи в выборку будет существование значения родительского ключа, равного любому внешнему. Это и есть условие ссылочной целостности. В качестве родительского ключа чаще всего выбирается первичный.

Пример

Подобрать продавцов и покупателей, живущих в одном городе:

Select имя_пок, имя_прод, покупатели.город From Покупатели, Продавцы

Where Покупатели.город=Продавцы.город;

Имя_пок

Имя_прод

Город

Комов

Иванов

Москва

Комов

Сидоров

Москва

Мохов

Петров

Тула

Глинка

Петров

Тула

Окулов

Иванов

Москва

Окулов

Сидоров

Москва

Заметим, что в списке выбираемых атрибутов имя_пок и имя_прод однозначно определяют таблицы, из которых выбираются. Атрибут город есть в обеих таблицах, поэтому следует уточнить, атрибут какой таблицы выбирается. В данном случае это безразлично, так как их значения равны.

В следующем примере ном_пок в таблице Покупатели играет роль первичного (родительского) ключа, а в таблице Заказы – внешнего.

Select имя_пок, ном_зак From Покупатели, Заказы

Where Заказы.ном_пок=Покупатели.ном_пок;

Так как на один внешний ключ в нашем случае приходится ровно один родительский, количество записей в выборке будет равно количеству записей в таблице Заказы. Если бы какое-то значение внешнего ключа не было найдено среди родительских, записей стало бы меньше (нарушение ссылочной целостности). Наоборот, если бы для одного значения внешнего ключа нашлось более одного значения родительского, записей стало бы больше (нарушение условия однозначности первичного ключа).

Конец примера

Соединение может применяться не только к двум таблицам. Таблиц может быть как больше, так и меньше, то есть одна таблица может соединяться сама с собой. Во втором случае возникает сложность, связанная с тем, что соединяемые таблицы должны иметь разные имена, иначе одноименные атрибуты различить невозможно. Для выхода из этого положения в SQL таблице может быть присвоено локальное, временное имя таблицы, которое используется наряду с основным. Это имя называется переменной области определения, или переменной корреляции, или псевдонимом. Таблица может иметь несколько псевдонимов. Существует два формата определения псевдонима:

Select <список атрибутов> From r пн1, s пн2 …

и

Select <список атрибутов> From r As пн1, s As пн2 …

Здесь пн1 и пн2 – псевдонимы таблиц r и s соответственно.

Пример

Найти заявки покупателей из городов, не совпадающих с городами продавцов. В этом случае соединяются три таблицы:

Select ном_зак, имя_пок From Заказы, Покупатели, Продавцы

Where Заказы.ном_пок=Покупатели.ном_пок

and Заказы.ном_прод=Продавцы.ном_прод

and Покупатели.город<>Продавцы.город;

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

Select a.имя_пок As пок1, b. имя_пок As пок1, a.значимость

From Покупатели a, Покупатели b

Where a.значимость=b.значимость;

пок1

пок2

Значимость

Комов

Окулов

100

Комов

Комов

100

Комов

Зимин

100

Окулов

Окулов

100

Окулов

Комов

100

Окулов

Зимин

100

Зимин

Зимин

100

Зимин

Окулов

100

Зимин

Комов

100

Емелин

Мохов

200

Емелин

Емелин

200

Мохов

Мохов

200

Мохов

Емелин

200

Попов

Попов

300

Попов

Глинка

300

Глинка

Попов

300

Глинка

Глинка

300

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

Select a.имя_пок, b.имя_пок, a.значимость From Покупатели a, Покупатели b

Where a.значимость=b.значимость;

and a.имя_пок < b.имя_пок;

пок1

пок2

Значимость

Комов

Окулов

100

Зимин

Окулов

100

Зимин

Комов

100

Емелин

Мохов

200

Глинка

Попов

300

Конец примера