
- •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. Выбрать все пары номеров поставщиков, таких, что оба поставщика в каждой паре находятся
7.3.7. Определить имена поставщиков, которые не поставляют деталь с номером 'р2'
SX.SNAME WHERE NOT EXISTS SPX
( SPX.Si = SX.St AND SPX.Pt = Pt ( 'P2' ) )
Обратите внимание, как просто это решение можно получить из решения приме- ра 7.3.3.
7.3.8. Определить номера поставщиков по крайней мере всех типов деталей, поставляемых поставщиком с номером *s2'
SX.SI WHERE FORALL SPX ( SPX.Si Ф Si ( 'S2' ) OR
EXISTS SPY ( SPY.Si = SX.Si AND SPY.Pi = SPX.Pi ) )
Переформулируем запрос в соответствии со следующим выражением: "Получить но- мера поставщиков (скажем, SX), таких, что для всех поставок SPY поставка осуществля- ется либо не от поставщика с номером 'S2', либо существует поставка SPY всех типов деталей, входящих в поставку SPX от поставщика SX".
Чтобы упростить формулировку таких сложных запросов, как этот, введем другое синтаксическое соглашение, называемое явной синтаксической формой для оператора логической импликации. Если р и q — формулы WFF, то выражение логической им- пликации вида
IF р THEN q END IF
также будет формулой WFF с семантикой, идентичной семантике следующей формулы. ( NOT р ) OR q
Таким образом, приведенное выше выражение может быть переписано так.
SX.Si WHERE FORALL SPX ( IF SPX.Si = Si ( 'S2' ) THEN
EXISTS SPY ( SPY.Si = SX.Si AND SPY.Pi = SPX.Pi )
END IF )
Дадим словесную формулировку этого запроса: "Получить номера поставщиков (скажем, SX), таких, что для всех поставок SPX в случае поставки от поставщика с номе- ром 'S2' существует поставка SPY всех типов деталей, входящих в поставку SPX^ot по- ставщика SX".
7.3.9. Получить номера деталей, которые либо весят более 16 фунтов, либо поставляются поставщиком с номером *S2\ либо и то, и другое
RANGEVAR PU RANGES OVER
( PX.Pi WHERE PX.WEIGHT > WEIGHT ( 16.0) ), ( SPX.Pi WHERE SPX.Si = Si ( 'S2' ) ) ;
PU.Pi
В эквивалентном выражении реляционной алгебры здесь могло бы использоваться явное объединение.
Ради интереса покажем альтернативную формулировку этого запроса. Однако тот факт, что каждый номер детали в переменной-отношении SP присутствует и в переменной- отношении Р, делает вторую формулировку не соответствующей "стилю объединения".
PX.PI WHERE PX.WEIGHT > WEIGHT ( 16.0 )
OR EXISTS SPX ( SPX.Pi = PX.Pi AND
SPX.Si = Si { 'S2' ) )
7.4. Сравнительный анализ реляционного исчисления и реляционной алгебры
J
s# |
SNAME |
STATUS |
CITY |
|
SPJ |
S# |
P# |
J# |
QTY |
SI |
Smith |
20 |
London |
|
SI |
PI |
JI |
200 | |
S2 |
Jones |
10 |
Paris |
|
SI |
PI |
J4 |
700 | |
S3 |
Black |
30 |
Paris |
|
S2 |
P3 |
JI |
400 | |
S4 |
Clark |
20 |
London |
|
S2 |
P3 |
J2 |
200 | |
S5 |
Adams |
30 |
Athens |
|
S2 |
P3 |
J3 |
200 | |
|
|
|
|
|
S2 |
P3 |
J4 |
500 | |
|
|
|
|
|
S2 |
P3 |
J5 |
600 | |
P# |
PNAME |
COLOR |
WEIGHT |
CITY |
|
S2 |
P3 |
J6 |
400 |
PI |
Nut |
Red |
12.0 |
London |
|
S2 |
P3 |
J7 |
800 |
P2 |
Bolt |
Green |
17.0 |
Paris |
|
S2 |
P5 |
J2 |
100 |
P3 |
Screw |
Blue |
17.0 |
Rome |
|
S3 |
P3 |
JI |
200 |
P4 |
Screw |
Red |
14.0 |
London |
|
S3 |
P4 |
J2 |
500 |
P5 |
Cam |
Blue |
12.0 |
Paris |
|
S4 |
P6 |
J3 |
300 |
P6 |
Cog |
Red |
19.0 |
London |
|
S4 |
P6 |
J7 |
300 |
|
|
|
|
|
S5 |
P2 |
J2 |
200 | |
|
|
|
|
|
S5 |
P2 |
J4 |
100 | |
J# |
JNAME |
CITY |
|
|
S5 |
P5 |
J5 |
500 | |
JI |
Sorter |
Paris |
|
|
S5 |
P5 |
J7 |
100 | |
J2 |
Display |
Rome |
|
|
S5 |
P6 |
J2 |
200 | |
J3 |
OCR |
Athens |
|
|
S5 |
PI |
J4 |
100 | |
J4 |
Console |
Athens |
|
|
S5 |
P3 |
J4 |
200 | |
J5 |
RAID |
London |
|
|
S5 |
P4 |
J4 |
800 | |
J6 |
EDS |
Oslo |
|
|
S5 |
P5 |
J4 |
400 | |
J7 |
Tape |
London |
|
|
S5 |
P6 |
J4 |
500 |
Рис. 7.1. База данных поставщиков, деталей и проектов (значения для примера)
В качестве основы для нашего примера используется не привычная база данных по- ставщиков и деталей, а ее расширенная версия, упоминавшаяся в упражнениях главы 4 и в других главах. Для удобства на рис. 7.1 приводится пример возможных значений для этой базы данных (это копия рис. 4.5 главы 4).
Рассмотрим теперь следующий запрос: "Получить имена поставщиков и названия го- родов, в которых находятся поставщики деталей по крайней мере для одного проекта в Афинах ('Athens'), поставляющих по крайней мере 50 штук каждой детали". Выраже- ние реляционного исчисления для этого запроса следующее.
( SX.SNAME, SX.CITY ) WHERE EXISTS JX FORALL PX EXISTS SPJX
( JX.CITY = 'Athens' AND JX.Ji = SPJX.Ji AND PX.PI = SPJX.PI AND SX.Si = SPJX.Si AND SPJX.QTY > QTY ( 50 ) )
Здесь SX, PX, JX и SPJX — переменные кортежей, получающие свои значения из пере- менных-отношений S, Р, J и SPJ соответственно. Теперь покажем, как можно вычислить это выражение, чтобы достичь требуемого результата.
Этап 1. Для каждой переменной кортежа выбираем ее область значений (т.е. набор всех значений для переменной), если это возможно. Выражение "выбираем, если воз- можно" подразумевает, что существует условие выборки, встроенное в фразу WHERE, ко- торую можно использовать, чтобы сразу исключить из рассмотрения некоторые корте- жи. В нашем случае выбираются следующие наборы кортежей.
SX РХ JX
SPJX
Все кортежи отношения S 5 кортежей
Все кортежи отношения Р 6 кортежей
Кортежи отношения J, в которых CITY = 'Athens' 2 кортежа
Кортежи отношения SPJ, в которых CITY > 50 24 кортежа
Этап 2. Строим декартово произведение диапазонов, выбранных на первом этапе. Вот результат.
s# |
SN |
STA- |
CITY |
P# |
PN |
COLOR |
WEIGHT |
CITY |
J# |
JN |
CITY |
S# |
P# |
J# |
QTY |
|
|
TUS |
|
|
|
|
|
|
|
|
|
|
|
|
|
SI |
Sm |
20 |
Lon |
PI |
Nt |
Red |
12.0 |
Lon |
J3 |
OR |
Ath |
SI |
PI |
Jl |
200 |
SI |
Sm |
20 |
Lon |
PI |
Nt |
Red |
12.0 |
Lon |
J3 |
OR |
Ath |
SI |
PI |
J4 |
700 |
(И т.д.) Все произведение содержит 5*6*2*24 = 1 440 кортежей.
Замечание. Для экономии места здесь это отношение полностью не приводится. Мы также не переименовывали атрибуты (хотя это следовало бы сделать во избежание дву- смысленности), а просто расположили их в таком порядке, чтобы было видно, какой ат- рибут Si относится, например, к отношению S, а какой — к отношению SPJ. Это также сделано для сокращения изложения.
Этап 3. Осуществляем выборку из построенного на этапе 2 произведения в соответ- ствии с частью "условие соединения" фразы WHERE. В нашем примере эта часть выглядит следующим образом.
JX.J# = SPJX.Jt AND PX.Pi = SPJX.PI AND SX.Si =SPJX.Si
Поэтому из произведения исключаются кортежи, для которых значение атрибута Sf из отношения поставщиков не равно значению атрибута Si из отношения поставок, зна- чение атрибута Pi из отношения деталей не равно значению атрибута Pi из отношения поставок, значение атрибута Л из отношения проектов не равно значению атрибута Ji из отношения поставок. Затем получаем подмножество декартова произведения, состоя- щее (как оказалось) только из десяти кортежей.
s# |
SN |
STA- TUS |
CITY |
P# |
PN |
COLOR |
WEIGHT |
CITY |
J# |
JN |
CITY |
S# |
P# |
J# |
QTY |
SI |
Sm |
20 |
Lon |
PI |
Nt |
Red |
12.0 |
Lon |
J4 |
Cn |
Ath |
SI |
PI |
J4 |
700 |
S2 |
Jo |
10 |
Par |
P3 |
Sc |
Blue |
17.0 |
Rom |
J3 |
OR |
Ath |
S2 |
P3 |
J3 |
200 |
S2 |
Jo |
10 |
Par |
P3 |
Sc |
Blue |
17.0 |
Rom |
J4 |
Cn |
Ath |
S2 |
P3 |
J4 |
200 |
S4 |
Cl |
20 |
Lon |
P6 |
Cg |
Red |
19.0 |
Lon |
J3 |
OR |
Ath |
S4 |
P6 |
J3 |
300 |
S5 |
Ad |
30 |
Ath |
P2 |
Bt |
Green |
17.0 |
Par |
J4 |
Cn |
Ath |
S5 |
P2 |
J4 |
100 |
S5 |
Ad |
30 |
Ath |
PI |
Nt |
Red |
12.0 |
Lon |
J4 |
Cn |
Ath |
S5 |
PI |
J4 |
100 |
S5 |
Ad |
30 |
Ath |
P3 |
Sc |
Blue |
17.0 |
Rom |
J4 |
Cn |
Ath |
S5 |
P3 |
J4 |
200 |
S5 |
Ad |
30 |
Ath |
P4 |
Sc |
Red |
14.0 |
Lon |
J4 |
Cn |
Ath |
S5 |
P4 |
J4 |
800 |
S5 |
Ad |
30 |
Ath |
P5 |
Cm |
Blue |
12.0 |
Par |
J4 |
Cn |
Ath |
S5 |
P5 |
J4 |
400 |
S5 |
Ad |
30 |
Ath |
P6 |
Cg |
Red |
19.0 |
Lon |
J4 |
Cn |
Ath |
S5 |
P6 |
J4 |
500 |
(Это отношение, конечно, представляет собой эквивалент результата операции со- единения.)
Этап 4. Применяем кванторы в порядке справа налево следующим образом.
Для квантора EXISTS RX (где RX — переменная кортежа, принимающая значение на некотором отношении г) проецируем текущий промежуточный результат, что- бы исключить все атрибуты отношения г.
Для квантора FORALL RX делим текущий промежуточный результат на отно- шение "выбранной области значений", соответствующее RX, которое было по- лучено выше. При выполнении этой операции также будут исключены все ат- рибуты отношения г.
Замечание. Под делением здесь подразумевается оригинальная операция деления Кодда (см. аннотацию к [6.3]).
В нашем примере имеем следующие кванторы. EXISTS JX FORALL PX EXISTS SPJX Значит, выполняются следующие операции.
1. (EXISTS SPJX) Проецируем, исключая атрибуты переменной-отношения SPJ (SPJ.Si, SPJ.Pi, SPJ. Ji и SPJ.QTY). В результате получаем следующее.
s# |
SN |
STATUS |
CITY |
P# |
PN |
COLOR |
WEIGHT |
CITY |
J# |
JN |
CITY |
SI |
Sm |
20 |
Lon |
PI |
Nt |
Red |
12.0 |
Lon |
J4 |
Cn |
Ath |
S2 |
Jo |
10 |
Par |
P3 |
Sc |
Blue |
17.0 |
Rom |
J3 |
OR |
Ath |
S2 |
Jo |
10 |
Par |
P3 |
Sc |
Blue |
17.0 |
Rom |
J4 |
Cn |
Ath |
S4 |
CI |
20 |
Lon |
P6 |
Cg |
Red |
19.0 |
Lon |
J3 |
OR |
Ath |
S5 |
Ad |
30 |
Ath |
P2 |
Bt |
Green |
17.0 |
Par |
J4 |
Cn |
Ath |
S5 |
Ad |
30 |
Ath |
PI |
Nt |
Red |
12.0 |
Lon |
J4 |
Cn |
Ath |
S5 |
Ad |
30 |
Ath |
P3 |
Sc |
Blue |
17.0 |
Rom |
J4 |
Cn |
Ath |
S5 |
Ad |
30 |
Ath |
P4 |
Sc |
Red |
14.0 |
Lon |
J4 |
Cn |
Ath |
S5 |
Ad |
30 |
Ath |
P5 |
Cm |
Blue |
12.0 |
Par |
J4 |
Cn |
Ath |
S5 |
Ad |
30 |
Ath |
P6 |
Cg |
Red |
19.0 |
Lon |
J4 |
Cn |
Ath |
2. (FORALL PX) Делим полученный результат на отношение Р. В результате имеем сле- дующее.
s# |
SN |
STATUS |
CITY |
J# |
JNAME |
CITY |
S5 |
Adams |
30 |
Athens |
J4 |
Console |
Athens |
(Теперь у нас есть место, чтобы показать отношение полностью, без сокращений.)
1. (EXISTS JX) Проецируем, исключая атрибуты отношения J (J. Jl, J.NAME и J.CITY). В результате получаем следующее.
S# |
SN |
STATUS |
CITY |
S5 |
Adams |
30 |
Athens |
Этап 5. Проецируем результат этапа 4 в соответствии со спецификациями в прото типе кортежа. В нашем примере прототип кортежа имеет следующий вид.
(SX.SNAME, SX.CITY)
Значит, конечный результат вычислений будет таков.
SNAME |
CITY |
Adams |
Athens |
Из сказанного выше следует, что начальное выражение исчисления семантически эк- вивалентно определенному вложенному алгебраическому выражению, и, если быть бо- лее точным, это проекция от проекции результата деления проекции выборки из произ- ведения четырех выборок (!).
Этим мы завершаем обсуждение примера. Конечно, можно намного улучшить ис- пользуемый алгоритм (глава 17, в частности аннотация к [17.5]). И хотя многие подроб- ности в пояснениях были опущены, этот пример вполне адекватно отражает общую идею работы алгоритма редукции.
Кстати, теперь можно объяснить одну из причин (и не только одну) определения Коддом ровно восьми алгебраических операторов. Эти восемь реляционных операторов образуют удобный целевой язык как средство возможной реализации реляционного ис- числения. Другими словами, для заданного языка, построенного на основе реляционного исчисления (подобно языку QUEL), один из возможных подходов реализации заключа-
ется в том, что организуется получение запроса в том виде, в каком он предоставляется пользователем. По существу, он будет являться просто выражением реляционного ис- числения, к которому затем можно будет применить определенный алгоритм редукции, чтобы получить эквивалентное алгебраическое выражение. Это алгебраическое выраже- ние, конечно, будет включать набор алгебраических операций, которые по определению реализуемы по самой своей природе. (Следующий этап состоит в оптимизации получен- ного алгебраического выражения, о чем речь пойдет в главе 17.)
Также следует отметить, что восемь алгебраических операторов Кодда являются мерой оценки выразительной силы любого языка баз данных. Это обстоятельство уже кратко упоминалось в главе 6, в конце раздела 6.6, а сейчас пришло время обсудить его подробнее.
Некоторый язык принято называть реляционно полным, если он по своим возмож- ностям по крайней мере не уступает реляционному исчислению. Иначе говоря, любое отношение, которое можно определить с помощью реляционного исчисления, можно определить и с помощью некоторого выражения рассматриваемого языка [6.1]. (В гла- ве 6 отмечалось, что "реляционно полный" значит "не уступающий по возможностям ре- ляционной алгебре", а не исчислению, но, как читатель вскоре убедится, это одно и то же. По сути, из самого существования алгоритма редукции Кодда немедленно следует, что реляционная алгебра обладает реляционной полнотой.)
Реляционную полноту можно рассматривать как основную меру выразительной силы языков баз данных в самом общем случае. В частности, так как реляционное исчисление и реляционная алгебра обладают реляционной полнотой, они могут служить основой для проектирования не уступающих им по выразительности языков без необходимости вы- полнять пересортировку для организации циклов. Это замечание особенно важно, если язык предназначается для конечных пользователей, хотя оно также существенно, если язык предназначается для использования прикладными программистами.
Далее, поскольку алгебра обладает реляционной полнотой, для доказательства того, что некоторый язык L также обладает реляционной полнотой, достаточно по- казать, что в языке L есть аналоги всех восьми алгебраических операций (на самом деле достаточно показать, что в нем есть аналоги пяти примитивных операций) и что операндами любой операции языка L могут быть любые выражения этого языка. Язык SQL — это пример языка, реляционную полноту которого можно доказать ука- занным способом (упр. 7.9). Язык QUEL — еще один пример подобного языка. В действительности на практике часто проще показать то, что в языке есть эквивален- ты операций реляционной алгебры, чем то, что в нем существуют эквиваленты вы- ражений реляционного исчисления. Именно поэтому реляционная полнота обычно определяется в терминах алгебраических выражений, а не в терминах выражений реляционного исчисления.
При этом важно понимать, что реляционная полнота необязательно влечет за собой полноту какого-либо другого рода. Например, желательно, чтобы язык также обеспечи- вал "вычислительную полноту", т.е. позволял вычислять результаты всех вычислимых функций. Заметим, что согласно нашему определению исчисление не обладает полнотой такого рода, хотя на практике подобная полнота для языка баз данных весьма желатель- на. Вычислительная полнота — это один из факторов, побудивших ввести в реляцион- ную алгебру операции EXTEND и SUMMARIZE (обсуждавшиеся в главе 6). В следующем раз- деле описано, как можно расширить реляционное исчисление, чтобы обеспечить в нем наличие аналогов этих операций.
Вернемся к вопросу эквивалентности алгебры и исчисления. Мы на примере по- казали, что любое выражение исчисления можно преобразовать в его некоторый ал- гебраический эквивалент, а значит, алгебра по крайней мере не уступает по своей мощности исчислению. Можно показать обратное: каждое выражение реляционной алгебры можно преобразовать в эквивалентное выражение реляционного исчисле- ния, а значит, исчисление по крайней мере не уступает по своей мощности реляци- онной алгебре. Полное доказательство этих утверждений можно найти, например, в книге Ульмана (Ullman) [7.13]. Отсюда следует, что реляционная алгебра и реляци- онное исчисление эквивалентны.