- •Isbn 5-8459-0138-3 (рус) isbn 0-201-38590-2 (англ)
- •Глава 2. Архитектура системы баз данных 65
- •Глава 6. Реляционная алгебра 192
- •Глава 7. Реляционное исчисление 243
- •Глава 8. Целостность данных 301
- •Глава 9. Представления 350
- •Часть 111
- •Часть IV
- •Глава 14. Восстановление 544 14.1. Введение 544
- •Глава 15. Параллельность 566
- •Часть V
- •Глава 16. Защита данных 602
- •Глава 17. Оптимизация 639
- •Глава 18. Отсутствующая информация 693
- •Глава 19. Наследование типов 725
- •Глава 20. Распределенные базы данных 767
- •Глава 21. Поддержка принятия решений 813
- •Глава 22. Хронологические базы данных 853
- •Глава 23. Логические системы управления базами данных 899
- •Часть VI
- •Глава 24. Объектные базы данных 944
- •Глава 25. Объектно-реляционные базы данных 999
- •Часть I (четыре главы) — это обширное введение в теорию баз данных вообще и реляционных баз данных в частности. Здесь также излагаются основы стандартно- го языка баз данных sql.
- •Часть IV. Две главы данной части — это несколько пересмотренные и расширен- ные версии глав 13 и 14 предыдущего издания.
- •Часть VI. Глава 24 является полностью переписанной и значительно улучшенной версией глав 22-24. Глава 25 почти полностью обновлена.
- •Часть I
- •Часть I состоит из четырех вводных глав.
- •1.1. Вводный пример
- •1.2. Что такое система баз данных
- •1.3. Что такое база данных Перманентные данные
- •1.4. Назначение баз данных
- •1.5. Независимость данных
- •1.6. Реляционные и другие системы
- •1.7. Резюме
- •2.1. Введение
- •2.2. Три уровня архитектуры
- •Внешний уровень (представления отдельных пользователей)Концептуальный уровень (обобщенное представление пользователей)
- •2.3. Внешний уровень
- •Отображение "внешний/концептуальный" схемы
- •Определение структур хранения (внутренняя схема)
- •Внешнее представление а Концептуальная схема
- •2.4. Концептуальный уровень
- •2.5. Внутренний уровень
- •2.6. Отображения
- •2.7. Администратор базы данных
- •2.8. Система управления базой данных
- •2.9. Система управления передачей данных
- •2.10. Архитектура "клиент/сервер"
- •2.11. Утилиты
- •2.12. Распределенная обработка
- •2.13. Резюме
- •3.1. Введение
- •3.2. Реляционная модель
- •3.3. Отношения и переменные-отношения
- •3.4. Смысл отношений
- •3.5. Оптимизация
- •3.6. Каталог
- •3.7. Базовые переменные-отношения и представления
- •3.8. Транзакции
- •3.9. База данных поставщиков и деталей
- •3.10. Резюме
- •Глава 4
- •4.1. Введение
- •4.2. Обзор языка sql
- •4.3. Каталог
- •4.4. Представления
- •4.5. Транзакции
- •4.6. Внедрение sql-операторов
- •4.7. Несовершенство языка sql
- •4.8. Резюме
- •Часть 9. Управление внешними данными (sql/med) Часть 10. Связь с объектным языком (sql/olb)
- •Часть II
- •Глава 5
- •5.1. Введение
- •5.2. Домены
- •5.3. Значения отношений
- •5.4. Переменные-отношения
- •5.5. Средства sql
- •5.6. Резюме
- •6.1. Введение
- •6.2. Реляционная замкнутость
- •6.3. Синтаксис
- •6.4. Семантика
- •6.5. Примеры
- •6.5.1. Получить имена поставщиков детали с номером 'р2'
- •6.5.2. Получить имена поставщиков по крайней мере одной красной детали
- •6.5.3. Получить имена поставщиков всех типов деталей
- •6.5.4. Получить номера поставщиков по крайней мере тех типов деталей, которые поставляет поставщик с номером 's2'
- •6.5.5. Получить все пары номеров поставщиков, находящихся в одном городе
- •6.5.6. Получить имена поставщиков, которые не поставляют деталь с номером 'р2'
- •6.6. Зачем нужна реляционная алгебра
- •6.7. Дополнительные операторы
- •6.8. Группирование и разгруппирование
- •6.9. Реляционные сравнения
- •6.10. Резюме
- •7.1. Введение
- •7.2. Исчисление кортежей
- •7.3. Примеры
- •7.3.5. Найти имена поставщиков по крайней мере одной детали, поставляемой поставщиком с номером 's2'
- •7.3.6. Выбрать имена поставщиков всех типов деталей
- •7.3.7. Определить имена поставщиков, которые не поставляют деталь с номером 'р2'
- •7.3.8. Определить номера поставщиков по крайней мере всех типов деталей, поставляемых поставщиком с номером *s2'
- •7.4. Сравнительный анализ реляционного исчисления и реляционной алгебры
- •7.5. Вычислительные возможности
- •7.5.1. Определить номера и вес в граммах всех типов деталей, вес которых превышает 10 ооо г
- •7.6.1. Выбрать номера поставщиков из Парижа со статусом, большим 20
- •7.7.1. Указать цвета деталей и названия городов, в которых находятся детали "не из Парижа" с весом, превышающим 10 фунтов
- •7.7.2. Для всех деталей указать номер и вес в граммах
- •7.7.3. Выбрать информацию обо всех парах поставщиков и деталей, находящихся в одном городе
- •7.7.4. Найти все пары названий городов, таких, что поставщик из первого города поставляет деталь, находящуюся во втором городе
- •7.7.5. Выбрать все пары номеров поставщиков, таких, что оба поставщика в каждой паре находятся
Часть 9. Управление внешними данными (sql/med) Часть 10. Связь с объектным языком (sql/olb)
Проекты SQL3, которые, как ожидается, будут утверждены в 1999 году, логически будут входить в части 1, 2, 4 и 5. Рабочие черновики, в которых описаны эти проекты, можно найти на Web-узле ftp:// jerry.ece.umassd.edu/isowg3/dbl/BASEdocs/public.
Замечание. Стоит упомянуть, что, хотя язык SQL часто считается международным стандартом "реляционных" баз данных, в документе стандарта это не утверждает- ся; на самом деле в документе вообще не используется термин "реляционный"! (Как говорилось ранее в сноске, в нем не упоминается и термин "база данных".)
4.23. International Organization for Standardization (ISO): Information Technology — Data- base Languages— SQL— Technical Corrigendum 2. Document ISO/IEC 9075:1992/Cor.2:1996(E).
Содержит большое количество исправлений и дополнений к начальной версии [4.22]. К сожалению, все исправления и дополнения практически не устраняют ни одной из проблем, указанных в [4.19].
4.24. Raymond A.L. and Daudenarde J.J. SQL and its Applications. — Englewood Cliffs, N.J.: Prentice-Hall, 1991.
Книга о языке SQL, содержащая практические советы и инструкции (почти поло- вина книги посвящена подробному обсуждению серии примеров применения прак- тических приложений).
4.25. Raymond A.L. and Nilsson J.F. An Access Specification Language for Relational Data Base System // IBM J.R&D. — May, 1979. — 23, № 3.
В публикации подробно рассматриваются вопросы, связанные с техникой компи- ляции в системе System R [4.11], [4.25], [4.26]. Для любого данного SQL-оператора оптимизатор системы генерирует программу на внутреннем языке ASL (Access Specification Language). Этот язык используется как интерфейс между оптимизато- ром и генератором кодов. (Генератор кодов, как следует из его названия, преобра- зует программу на языке ASL в машинный код.) В языке ASL есть, например, опе- раторы scan (поиск) и insert (вставить), применяемые к таким объектам, как ин- дексы и хранимые файлы. Язык создавался, чтобы весь процесс трансляции стал управляемым. Это достигалось путем разбиения процесса трансляции на множест- во четко определенных подпроцессов.
4.26. Raymond A.L. and Bratford W.W. Compilation of High-Level Data Language. IBM Re- search Report RJ2598. — August, 1979.
В системе System R впервые была применена идея компиляции запросов перед их выполнением и рекомпиляции запросов, если физическая структура базы данных значительно изменялась на каком-то переходном этапе. В этой статье подробно описывается механизм компиляции и рекомпиляции, но не затрагиваются вопросы оптимизации (эта актуальная тема освещается в [17.34]).
4.27. Melton J., Simon A.R. Understanding The New SQL: A Complete Guide. — San Mateo, Calif.: Morgan Kaufmann, 1993.
Руководство по стандарту SQL/92 (как представлена сама книга). Один из авторов (Melton) был редактором первоначальных спецификаций стандарта SQL/92 [4.22].
4.28. Reisner P., Воусе R.F., Chamberlin D.D. Human Factors Evaluation of Two Data Base Query Languages: SQUARE and SEQUEL // Proc. NCC 44.— Anaheim, Calif.; Montvale, N.J.: AFIPS Press, May, 1975.
Язык SEQUEL [4.8], предшественник языка SQL, был разработан на базе более раннего языка SQUARE. Эти два языка, в основном, совпадали, но в языке SQUARE использовался математический синтаксис, а в языке SEQUEL — ключе- вые слова из английского языка, такие как SELECT, FROM, WHERE и т.д. В статье при- ведены отчеты по ряду исследований, в которых изучалась практичность этих язы- ков; в качестве объектов использовались студенты колледжа. В результате такого исследования в язык SEQUEL были внесены некоторые изменения [4.9].
4.29. Rozenshtein D., Abramovich A., Birger Е. Optimizing Transact-SQL: Advanced Programming Techniques. — Fremont, Calif.: SQL Forum Press, 1995. Язык Transact-SQL— это диалект языка SQL, который поддерживается такими продуктами, как Sybase и SQL Server. В этой книге рассматривается ряд приемов программирования для языка Transact-SQL, которые основаны на использовании характеристических функций (определенных авторами как средства, позволяю- щие программистам кодировать логические условия в виде... выражений в предло- жениях SELECT, WHERE, GROUP BY и SET). Хотя эти идеи выражены в терминах языка Transact-SQL, на самом деле они имеют более широкую область применения. Замечание. Необходимо отметить, что слово "optimizing", которое входит в назва- ние книги, не имеет отношения к оптимизатору СУБД. Напротив, здесь подразуме- вается оптимизация, которая может выполняться самими пользователями вручную.
Ответы к некоторым упражнениям
4.1. CREATE TABLE S
( SI CHAR(5),
SNAME CHARf20), STATUS NUMERIC(5), CITY CHAR(15), PRIMARY KEY ( S# ) ) ;
CREATE TABLE P
( PI CHAR(6),
PNAME CHAR(20), COLOR CHAR(6), WEIGHT NUMERIC(5,1), CITY CHAR(15), PRIMARY KEY j Pi ) ) ;
CREATE TABLE J
( Jl CHAR(4),
JNAME CHARj20), CITY CHAR!15), PRIMARY KEY ( Ji ) ) ;
CREATE TABLE SPJ
( SI CHAR(5),
Pt CHAR(6),
Ji CHAR(4),
QTY NUMERIC(9), PRIMARY KEY ( Si, Pi, Jt ), FOREIGN KEY ( St ) REFERENCES S, FOREIGN KEY ( Pt ) REFERENCES P, FOREIGN KEY ( Jt ) REFERENCES J ) ;
4.4. Ниже приведены ответы к отдельным пунктам упражнения.
а) INSERT INTO S (St, SNAME, CITY )
VALUE ( 'S10', 'Smith', 'New York' ) ;
Значение столбца STATUS здесь установлено равным значению по умолчанию.
б) UPDATE Р
SET COLOR = 'Orange' WHERE COLOR - 'Red' ;
в) DELETE FROM J
WHERE Jt NOT IN ( SELECT Ji FROM SPJ ) ;
Обратите внимание на вложенный подзапрос и оператор IN (а точнее, на отрица- ние оператора IN) в ответе в. Такие подзапросы рассматриваются в главе 7.
4.5. Отметим, что могут существовать поставщики, которые не поставляют деталей ни для одного проекта; в следующем ответе рассматриваются именно такие постав- щики (только такие?). Сначала определим два курсора, CS и CJ.
EXEC SQL DECLARE CS CURSOR FOR
SELECT S.St, S.SNAME, S.STATUS, S.CITY
FROM S
ORDER BY Si ;
EXEC SQL DECLARE CJ CURSOR FOR
SELECT J.Jt, J.JNAME, J.CITY FROM J WHERE J.Jt IN
( SELECT SPJ.Jt FROM SPJ
WHERE SPJ.Si = :CS Si ) ORDER BY Ji ;
(Снова обратите внимание на вложенный подзапрос и оператор IN.) Когда курсор С J открыт, базовая переменная CS_S# содержит значение номера по- ставщика, получаемое с помощью курсора CS. Логика процедуры, по существу, следующая.
EXEC SQL OPEN CS
DO <для всех строк S, доступных через CS>;
EXEC SQL FETCH CS INTO :CS SI, :CS SN, :CS ST, :CS SC ; print CS SI, CS SN, CS ST,~CS SC f EXEC SQL~OPEN CJ ;
DO <для всех строк J, доступных через CJ>;
EXEC SQL FETCH CJ INTO :CJ_J|, :CJ_JN, :CJ_JC ; print CJ JI, CJ JN, CJ JC ~ END DO ;""
EXEC SQL CLOSE CJ ; END DO ;
EXEC SQL CLOSE CS ;
4.6. Это хороший пример задачи, которую с помощью языка SQL в его обычной форме решить полностью нельзя. Нужно "разобрать" данную деталь на п уровней при ус- ловии, что и во время написания программы неизвестно. Сравнительно простой способ формирования таких и уровней (если бы это было возможно) мог бы быть реализован с помощью рекурсивной программы, в которой каждый рекурсивный вызов создает новый курсор, как показано ниже.
CALL RECURSION ( GIVENPl ) ;
RECURSION: PROC ( UPPER Pi ) RECURSIVE ; DCL UPPER Pi ... ; DCL L0WER~P| ... ;
EXEC SQL DECLARE С "reopenable" CURSOR FOR
SELECT MINOR Pi
FROM PART STRUCTURE
WHERE MAJOR Pi = :UPPER Pt ; print UPPER_Pi ;
/* вывести значение UPPER Pi */ EXEC SQL OPEN С ;
DO <для всех строк PART_STRUCTURE, доступных через О ;
EXEC SQL FETCH С INTO :L0WER_Pi ;
CALL RECURSION ( LOWER_Pt ) ; END DO j
EXEC SQL CLOSE С ; END PROC ;
Здесь подразумевается, что фиктивная спецификация "reopenable" ("повторно от- крываемый") в операторе DECLARE CURSOR означает допустимость операции OPEN даже в том случае, если курсор уже открыт. В результате такой операции создается новый экземпляр курсора для данного табличного выражения (использующего те- кущие значения любых базовых переменных, на которые есть ссылки в этом вы- ражении). Далее подразумевается, что ссылки на такой курсор в операторе FETCH и других являются ссылками на "текущий" экземпляр и что оператор CLOSE уничто- жает именно этот экземпляр и восстанавливает предыдущий экземпляр как
"текущий". Другими словами, подразумевается, что повторно открываемый курсор формирует стек, который обслуживается операторами OPEN и CLOSE так же, как обычный стек обрабатывается операторами push и pop.
К сожалению, подобные допущения на сегодняшний день чисто гипотетические. В языке SQL пока нет таких средств, как повторно открываемый курсор (в действи- тельности попытка повторно открыть курсор приведет к ошибке). Приведенный код недопустим. Но этот пример наглядно показывает, что "повторно открываемые кур- соры" были бы очень полезным дополнением к современному варианту языка SQL. Поскольку предыдущая процедура не справляется с поставленной задачей, мы вкратце приведем одну из возможных процедур (но не наиболее эффективную), которая позволяет решить задачу.
CALL RECURSION ( GIVENPi ) ; RECURSION: PROC ( UPPER Pi ) RECURSIVE ; DCL UPPER Pi ... ;
DCL L0WER~Pi ... INITIAL ( ' ' );
EXEC SQL DECLARE С CURSOR FOR
SELECT MINOR Pi
FROM PART STRUCTURE
WHERE MAJ0R_Pi = :UPPER_Pi
AND MINOR Pi > :LOWER Pi
ORDER BY MIN0R_Pi ; print UPPER_Pi ; DO <без ограничение ; EXEC SQL OPEN С
EXEC SQL FETCH С INTO :LOWER Pi ; EXEC SQL CLOSE С ;
IF <нет выбранных lower Pi> THEN RETURN ; END IF ; IF <есть выбранные lower Pi> THEN
CALL RECURSION ( LOWER Pi ) ; END IF ; END DO ; END PROC ;
Заметьте, что в этом решении один и тот же курсор используется в каждом вызове подпрограммы RECURSION (но каждый раз при ее вызове динамически создаются но- вые экземпляры переменных UPPER_Pi и L0WER_Pt, причем в конце вызова эти экзем- пляры уничтожаются). В связи с данным фактом мы использовали следующий трюк.
... AND MIN0R_Pi > :L0WER_Pi ORDER BY MIN0R_Pf
Так что при каждом вызове подпрограммы RECURSION все промежуточные компо- ненты (L0WER_Pi) текущего значения UPPER_Pi, которые уже были обработаны, просто игнорируются.
Обсуждение некоторых альтернативных подходов к этой задаче вы найдете в [4.5], [4.7]. В главе 6 (в конце раздела 6.7) описывается оператор, имеющий отношение к данному вопросу. Он называется транзитивным замыканием (transitive closure). В приложении Б приводится обзор некоторых возможностей в стандарте SQL3, ко- торые также имеют отношение к данной проблеме.