- •Часть 2. Реляционная модель.
- •Глава 4. Реляционные объекты данных: домены и отношения.
- •4.1. Вводный пример
- •4.2. Домены
- •4.3. Отношения
- •4.4. Виды отношений
- •4.5. Отношения и предикаты
- •4.6. Реляционные базы данных
- •4.7. Резюме
- •Глава 8.
- •8.1. Введение
- •8.2. Определение данных
- •8.3. Обработка данных: операции выборки
- •8.3.1. Получить цвета и города для деталей "не из Парижа" с весом, большим десяти
- •8.3.2. Для всех деталей получить номер детали и ее вес в граммах
- •8.3.3. Получить полную информацию обо всех поставщиках
- •8.3.4. Получить информацию обо всех парах поставщиков и деталей, совмещенных в одном городе
- •8.3.5. Получить все пары имен городов, таких что поставщик, находящийся в первом городе, поставляет деталь, хранящуюся во втором городе
- •8.3.6. Получить все пары номеров поставщиков, таких что оба поставщика в каждой паре размещаются в одном и том же городе
- •8.3.7. Получить общее число поставщиков
- •8.3.8. Получить максимальное и минимальное количество для детали р
- •8.3.9. Для каждой поставляемой детали получить номер детали и общее количество поставки
- •8.3.10. Получить номера для всех деталей, поставляемых более чем одним поставщиком
- •8.3.11. Получить имена поставщиков, поставляющих деталь р2
- •8.3.12. Получить имена поставщиков, поставляющих по крайней мере одну красную деталь
- •8.3.13. Получить номера поставщиков, статус которых меньше текущего максимального статуса в таблице s
- •8.3.14. Получить имена поставщиков, поставляющих деталь р2
- •8.3.15. Получить имена поставщиков, которые не поставляют деталь р2
- •8.3.16. Получить имена поставщиков, поставляющих все детали
- •8.3.17. Получить номера деталей, которые или весят более 16 фунтов, или поставляются поставщиком s2, или и то и другое
- •8.4. Обработка данных: операции обновления
- •Table-term
- •I join-table-expression
- •8.6. Условные выражения
- •8.7. Скалярные выражения
- •8.8. Встроенный sql
- •8.8.1. Единичный select. Получить статус и город для поставщика, чей номер поставки задан базовой переменной givens#
- •8.8.2. Insert. Вставить новую деталь в таблицу р (номер детали, ее назв. И вес определены базовыми переменными р#, pname, pwt соответственно, цвет и город неизвестны)
- •8.8.3, Update. Увеличить статус всех поставщиков из Лондона на значение, определенное базовой переменной raise
- •8.8.4. Delete. Удалить все поставки для поставщиков из города,
- •8.9. Резюме
8.3.17. Получить номера деталей, которые или весят более 16 фунтов, или поставляются поставщиком s2, или и то и другое
См. аналогичный пример в главе 7.
SELECT P.P#
FROM P
WHERE P.WEIGHT > 16
UNION
SELECT SP.P#
FROM SP
WHERE SP.S# = 'S2' ;
Лишние повторяющиеся строки всегда исключаются из результата безусловных операторов union, intersect или except (оператор except в языке SQL служит аналогом операции minus реляционной алгебры). Но язык SQL также предоставляет и уточненные варианты операторов: UNION ALL, INTERSECT ALL И EXCEPT ALL, при которых повторяющиеся строки(если они есть) сохраняются. Примеры с этими вариантами операторов умышленно опускаются.
В заключение отметим, что хотя список примеров выборок был довольно большим, тем не менее, многие возможности SQL даже не упоминались. Язык SQL действительно чрезвычайно избыточный в том смысле, что почти всегда предоставляет множество разных способов формулировки одного и того же запроса, и нам не хватит места, чтобы описать все возможные формулировки и все возможные опции даже для сравнительно небольшого числа примеров, которые рассматривались в этой главе.
8.4. Обработка данных: операции обновления
Как уже упоминалось, язык обработки данных DML включает три операции обновления: INSERT (вставка), UPDATE (изменение) и DELETE (удаление). Приведем несколько простых примеров, которые, как мы полагаем, понятны без комментариев.
8.4.1. Вставка одной строки
INSERT
INTO P ( Р#, PNAME, COLOR, WEIGHT, CITY )
VALUES ( 'P8', 'Sprocket', 'Pink', 14, 'Nice' ) ;
8.4.2. Вставка нескольких строк
INSERT
INTO TEMP ( S#, CITY )
SELECT S.S#, S.SITY
FROM S
WHERE S.STATUS > 15 ;
8.4.3. Обновление нескольких строк
UPDATE Р
SET COLOR = 'Yellow',
WEIGHT = P.WEIGHT + 5 WHERE P.CITY = 'Paris' ;
8.4.4. Обновление нескольких строк
UPDATE P
SET CITY = ( SELECT S.CITY
FROM S
WHERE S.S# = 'S5' ) WHERE P.COLOR = 'Red' ;
8.4.5. Удаление нескольких строк
DELETE
FROM SP
WHERE 'London' =
( SELECT S.CITY
FROM S
WHERE S.S#=SP.S#);
8.5. Табличные выражения
Для исчерпывающего освещения табличных выражений в этой книге не хватило бы места. Однако, по крайней мере, для ссылок, на рис. 8.1 приводится достаточно полное описание BNF-грамматики для таких выражений (грамматика описана полностью, за исключением нескольких опций, имеющих отношение к null-значениям). Также в этом разделе делается попытка разобраться с одним специальным случаем, бесспорно, наиболее важным на практике, а именно выражениями выборки.
Выражением выборки можно считать, нестрого говоря, табличное выражение, не использующее операторов union, intersect или except ("нестрого", поскольку такие операторы могут быть включены в выражения, которые вложены внутри выражения выборки). Как показано на рис. 8.1, выражение выборки содержит несколько компонентов: ИНСТРУКЦИИ SELECT, FROM, WHERE, GROUP BY И HAVING (последние три из них не обязательны). Теперь рассмотрим последовательно каждый из этих компонентов.
Инструкция SELECT
Инструкция select записывается в виде
SELECT [ ALL | DISTINCT ] select-item-commalist
Пояснения:
1. Список элементов выборки select -item-commalist не должен быть пустым. Ниже элементы выборки рассматриваются подробно.
2. Если ни ключевое слово all, ни distinct не указаны, то подразумевается all.
3. В данный момент подразумевается, что вычисления для инструкций from, where, group by и having уже проведены. Не имеет значения, какая из этих инструкций указана, а какая опущена: концептуальный результат их вычисления всегда является таблицей (возможно, "сгруппированной" таблицей — см. ниже), на которую мы будем ссылаться как на таблицу T1 (хотя концептуальный результат в действительности не именован).
4. Пусть Т2 будет таблицей, производной от таблицы T1 путем вычисления указанного списка элементов по таблице T1 (см. ниже).
5. Пусть ТЗ будет таблицей, производной от таблицы Т2 в результате исключения лишних повторяющихся строк из таблицы Т2, если указано ключевое слово distinct, или таблицей, идентичной T2, в противном случае.
6. Таблица ТЗ будет конечным результатом.
А теперь возвратимся к элементам выборки. Необходимо рассмотреть два случая, однако второй случай — это просто сокращение списка элементов выборки, полученного в первом случае, т.е. основным является первый случай.
Случай 1. Элемент выборки имеет следующий вид:
scalar-expression [ [ AS ] column ]
• Скалярное выражение (scalar-expression) обычно (но не обязательно) включает один или более столбцов таблицы T1 (см. пояснения выше). Для каждой строки таблицы Т1 вычисляется скалярное выражение, дающее скалярный результат. Список таких результатов (соответствующий вычислению всех элементов выборки в инструкции select по отдельной строке таблицы T1) состоит из единственной строки таблицы Т2. Если в элементе выборки присутствует ключевое слово as, то неуточненное имя столбца из этой инструкции назначается как имя соответствующего столбца таблицы T2(//////) (необязательное ключевое слово as здесь просто помеха и может быть опущено без какого-либо ущерба). Если в элементе выборки ключевое слово as отсутствует, возможны два варианта: для элемента выборки, состоящего просто из имени столбца (возможно, уточненного), такое имя назначается как имя соответствующего столбца таблицы T2; в противном случае соответствующий столбец таблицы Т2 фактически не имеет имени.
////////// Вследствие того что это фактически имя столбца таблицы Т2, а не T1, любое имя, представленное инструкцией AS, не может использоваться в инструкциях WHERE, GROUP BY и HAVING (если они есть), непосредственно включаемых в конструкцию таблицы T1. Однако на это имя можно ссылаться в соответствующей инструкции ORDER BY, а также во "внешнем" табличном выражении, которое содержит рассматриваемое вложенное в него выражение выборки.//////////
table-expression
: := join-table-expression
| nоn join-table-expression
join-table-expression
: := table-reference [ NATURAL ] JOIN
table-reference [ ON conditional-expression
| USING ( column-commalist ) ] | table-reference CROSS JOIN table-reference
I ( join-table-expression )
table-reference
: := table [ [ AS ] range-variable
[ ( column-commalist ) ] ]
I ( table-expression ) [ AS ] range -variable
[ ( column-commalist ) ]
I join-table-expression
nonjoin-table-expression
: := nonjoin-table-term
| table-expression UNION [ ALL ]
[ corresponding [ BY ( column-commalist ) ] ]
table-term
| table-expression EXCEPT [ ALL ]
[ corresponding [ BY ( column-commalist ) ] ]