- •Часть 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. Резюме
4.2. Домены
В качестве отправной точки возьмем наименьшую семантическую единицу данных, которая предполагается отдельным значением данных (таким как отдельный номер поставщика, отдельный вес детали или отдельное количество деталей в поставке). Мы будем называть такие значения скалярами (хотя этот термин редко используется в реляционной литературе). Скалярные значения представляют собой "наименьшую семантическую единицу данных" в том смысле, что они атомарные: у них нет внутренней структуры (т.е. они неразложимы) в реляционной модели, а значит, и при рассмотрении в реляционной СУБД. Обратите особое внимание на то, что не иметь внутренней структуры при рассмотрении в реляционной модели вовсе не значит не иметь внутренней структуры вообще. Например, название города, конечно же, имеет внутреннюю структуру (оно состоит из последовательности букв); однако, разложив название по буквам, мы потеряем значение. Значение станет понятным, лишь в том случае, если буквы сложены вместе и в правильной последовательности.
Замечание. Мы мимоходом заметили, что понятие "атомарности скалярных значений" довольно расплывчатое [4.8, 4.15]. Однако дальнейшее обсуждение этого вопроса отложено для следующих глав книги; а сейчас будем полагать, что это понятие интуитивно понятно.
Теперь можно определить домен как именованное множество скалярных значений одного типа. Например, домен номеров поставщиков — это множество всех возможных номеров поставщиков; домен количества деталей для поставок — это множество всех целых чисел, больших нуля и меньших, скажем, 10 000. Итак, домены являются общими совокупностями значений, из которых берутся реальные значения атрибутов. Точнее, каждый атрибут должен быть определен на единственном домене (или на основе одного домена); это значит, что значения атрибута должны браться из этого домена. Например, атрибут номера детали для отношения Р и атрибут номера детали для отношения SP определены на домене номера детали (потому что эти два атрибута, бесспорно, представляют номера деталей). Другими словами, в любой момент времени каждое значение Р# в отношении Р должно быть значением из домена номера детали, то же верно для значения Р# в отношении SP. Иными словами, в любой момент времени набор значений Р# в отношении Р является некоторым подмножеством множества значений домена номера детали, и то же верно для значения Р# в отношении SP.
Между прочим, обратите внимание, что обычно в любой момент времени в домене будут значения, не являющиеся значением ни одного из атрибутов, соответствующих этому домену. Например, если значение Р8 — допустимое значение детали, то оно входит в домен номера детали, даже если в нашем отношении Р из примера базы данных поставщиков и деталей нет детали Р8, т.е. в данный момент не существует такой детали.
Сравнения, ограниченные доменом
В чем состоит значение доменов? Один из наиболее важных ответов на этот вопрос следующий: домены ограничивают сравнения. Поясним сказанное. Рассмотрим два запроса SQL к базе данных поставщиков и деталей (заметьте, что оба запроса используют соединение):
SELECT... SELECT .....
FROM P, SP FROM Р, SP
WHERE P.P# = SP.P# WHERE P.WEIGHT = SP.QTY ;
Один из этих запросов, а именно левый, возможно, имеет смысл, тогда как правый, скорее всего, — нет. Откуда это известно? С формальной точки зрения ответ заключается в том, что запрос слева использует сравнение между атрибутами Р.Р# и SP.P#, которые (как уже упоминалось) определены на одном и том же домене, в то время как запрос справа использует сравнение между атрибутами P.WEIGHT и SP.QTY, которые, вероятно, определены на разных доменах. (Мы здесь говорим "вероятно", поскольку, хотя вес и количество являются числами, это числа разного "сорта". Не имеет смысла сравнивать вес и количество. Поэтому домены веса и количества должны быть различными.)
Следовательно, в соответствии с предыдущими рассуждениями, если значения двух атрибутов взяты из одного и того же домена, тогда сравнения, а отсюда и соединения, объединения и многие другие операции, использующие такие два атрибута, тоже, вероятно, будут иметь смысл, так как в них сравнивается подобный атрибут с подобным. И наоборот, если значения двух атрибутов взяты из различных доменов, тогда сравнения и другие операции, наверное, не будут иметь смысла. Поэтому преимущество системы поддержки доменов заключается в том, что такая система способна предотвратить грубые ошибки. Обратите внимание, что здесь легко допустить механическую ошибку, например набрав S#- вместо Р#. Если пользователь попробует выполнить операцию, использующую сравнение значений разных доменов, система прервет свою работу и сообщит пользователю о возможной ошибке. (Мы говорим "возможной", поскольку могут быть обстоятельства, при которых такое сравнение не является ошибкой. Но об этом в следующих частях книги.)
Между прочим, следует отметить, что хотя все примеры, которые мы приводили, были выражены в терминах языка SQL, этот язык на самом деле не поддерживает доменов в том смысле, который мы им придаем. Оба указанных выше запроса допустимы в SQL. Однако второй, конечно же, даст бессмысленный ответ.
Определение данных
Один вопрос, который еще, возможно, не ясен читателю, заключается в том, что домены прежде всего имеют концептуальную природу. Они могут быть или не быть явно сохранены в базе данных как реальные наборы значений; фактически в большинстве случаев они не сохраняются. Но они должны быть, по крайней мере, определены в рамках определений базы данных (имеется в виду в системе, поддерживающей понятие домена в полной мере; но как уже отмечалось, большинство сегодняшних продуктов такой поддержки не обеспечивают); и тогда каждое определение атрибута должно включать ссылку на соответствующий домен, таким образом системе будет известно, какие атрибуты можно сравнивать, а какие — нет.
Теперь, чтобы конкретизировать идеи реляционной модели (как в этом разделе, так и во всей части), мы будем использовать гипотетический реляционный язык для иллюстрации этих идей. Операторы языка будут постепенно вводиться по ходу изложения. Ясно, что в первую очередь нам нужен способ создания нового домена:
CREATE DOMAIN domain data-type ;
Здесь domain— это имя нового домена, a data-type соответствует типу данных, например CHAR(n) или numeric (n). Замечание. Далее в книге мы обсудим некоторые дополнительные компоненты оператора create domain, не показанные выше.
На рис. 4.3 (такой же рисунок уже приводился в главе 3) показано, как с помощью этого языка можно определить базу данных поставщиков и деталей. Обратите внимание, что в этом примере наряду с операторами create domain используются операторы CREATE BASE RELATION. Полное описание оператора CREATE BASE RELATION дано ниже в этой главе; здесь мы лишь отметим, что каждое определение атрибута в операторе create base relation включает ссылку на соответствующий домен.
При создании нового домена с помощью оператора create domain СУБД создает запись в каталоге с описанием этого нового домена. (Чтобы вспомнить, что такое каталог, обратитесь еще раз к главе 3.) Точно так же при создании нового отношения с помощью оператора create base relation СУБД создает запись в каталоге с описанием этого нового отношения.
Замечание о названиях. Для определенности будем предполагать следующие ограничения на названия:
• Домены имеют уникальные имена в базе данных.
• Именованные отношения имеют уникальные имена в базе данных.
• Атрибуты имеют уникальные имена в содержащем их отношении (даже если содержащее их отношение не именовано!).
Вообще говоря, атрибут может иметь как имя, совпадающее с именем соответствующего домена, так и отличное от него имя. Очевидно, чтобы избежать двусмысленности, следует использовать разные имена (в частности, если два атрибута в одном отношении основаны на одном домене). Однако в общем желательно называть атрибуты таким же именем, что и лежащий в основе домен, или, по крайней мере, называть так, чтобы, например, в имени атрибута содержалась ключевая часть имени домена. Мы следуем этому указанию и в примере на рис. 4.3.
Можно дополнительно придерживаться другого общего соглашения и полностью опускать ссылку к основному домену из определения любого атрибута, который имеет то же самое имя, что и домен. Например, оператор create base relation для базового отношения S может быть упрощен:
CREATE BASE RELATION S
( S#, SNAME DOMAIN (NAME), STATUS, CITY )
PRIMARY KEY ( S# ) ;
CREATE DOMAIN S# CHAR(5) ;
CREATE DOMAIN NAME CHAR(20) ;
CREATE DOMAIN STATUS NUMERIC (5) ;
CREATE DOMAIN CITY CHAR(15) ;
CREATE DOMAIN P# CHAR (6) ;
CREATE DOMAIN COLOR CHAR(6) ;
CREATE DOMAIN WEIGHT NUMERIC(5) ;
CREATE DOMAIN CITY NUMERIC (9) ;
CREATE BASE RELATION S
( S# DOMAIN ( S# ),
SNAME DOMAIN ( NAME ) ,
STATUS DOMAIN ( STATUS ),
CITY DOMAIN ( CITY ) )
PRIMARY KEY ( S# ) ;
CREATE BASE RELATION P
( P# DOMAIN ( P# ),
PNAME DOMAIN ( NAME ),
COLOR DOMAIN ( COLOR ),
WEIGHT DOMAIN (WEIGHT ),
CITY DOMAIN ( CITY ) )
PRIMARY KEY ( P# ) ;
CREATE BASE RELATION SP
( S# DOMAIN ( S# ),
P# DOMAIN ( P# ),
QTY DOMAIN ( QTY ) )
PRIMARY KEY ( S#, P# )
FOREIGN KEY ( S# ) REFERENCES S
FOREIGN KEY ( P# ) REFERENCES P;
Рис. 4.3. База данных поставщиков и деталей (определение данных)
Удаление доменов. Мы уже знаем, как создать новый домен. Должна также быть возможность удалить существующий домен, если мы больше в нем не нуждаемся:
DESTROY DOMAIN domain ;
Здесь domain — это имя удаляемого домена. С помощью этой операции удаляется элемент каталога, описывающий домен, поэтому такой домен становится неизвестным для системы. (До особого указания будем подразумевать, что операция destroy domain просто не будет выполняться, если какое-нибудь базовое отношение в этот момент еще включает атрибут, который определен на указанном домене.)
Запросы, основанные на доменах. Вот другой пример практического значения доменов. Рассмотрим запрос, который формулируется так:
"Какие отношения в базе данных содержат какую-либо информацию, имеющую отношение к поставщикам?"
Этот вопрос может быть сформулирован более точно:
"Какие отношения в базе данных включают атрибут, который определен на домене поставщика?"
В системе, поддерживающей понятие домена, такой запрос, как видим, транслируется в простой запрос к каталогу. В системе, которая не поддерживает домены, очевидно, невозможно обратиться с запросом к каталогу относительно доменов. Можно обратиться только через атрибуты. Запрос по атрибутам достигнет указанной цели лишь в том случае, если разработчик базы данных следует рекомендациям по наименованиям, приведенным выше (другими словами, если он соблюдает в базе данных порядок по отношению к доменам).
Домены и типы данных
Включение этого раздела вызвано тем, что многие читатели уже вполне готовы понять следующее: домен — это на самом деле ни больше ни меньше, чем тип данных (как это понимается в современных языках программирования). Например, в языке программирования Pascal допустимы следующие выражения:
type Day = ( Sun, Mon, Tue, Wed, Thu, Fri, Sat ) ;
var Today : Day ;
Здесь мы имеем определенный пользователем тип, названный "Day" (имеющий в точности семь допустимых значений), и переменную, названную "Today", принадлежащую этому типу данных (а значит, ограниченную этими семью значениями). Очевидно, что эта ситуация полностью аналогична ситуации в реляционной базе данных, когда мы имеем домен, названный "Day", и атрибут, названный "Today". Более того, существуют языки программирования, например SIMULA 67, MODULA-2 или Ada (однако Pascal в их число не входит), которые поддерживают некоторые или даже все функции, обычно приписываемые доменам в реляционной модели [4.8].
Исходя из того, что домен в своей основе является просто типом данных, было бы неверно утверждать, что СУБД вовсе не поддерживают доменов. В действительности системы поддерживают домены в очень примитивном смысле, так же как они предоставляют определенные встроенные (т.е. определенные системой) примитивные типы данных, такие как тип целых чисел или тип чисел с плавающей точкой. Но, если говорить о поддержке доменов в контексте реляционных систем, мы имеем в виду нечто большее, чем такая примитивная поддержка, а именно то, что система должна обеспечивать возможность пользователю создавать свои, более сложные типы данных, такие как "номера поставщиков", "номера деталей", "названия городов", "цвета" и т.д., а также обеспечивать все возможности для работы с этими типами.
Что же включают в себя возможности для работы с этими типами? Конечно, это не только описанные выше сравнения, ограниченные доменами. На самом деле понятие домена значительно сложнее, чем может показаться с первого взгляда (именно поэтому многие современные системы и не поддерживают его). Однако из-за большого объема материала мы некоторое время не будем касаться дальнейших следствий. Поэтому пока будем предполагать, что поддержка доменов означает только одно: если два скалярных значения можно сравнивать, то они принадлежат одному домену. Нужно понимать, что это весьма существенное упрощение, и мы прибегли к нему, чтобы упростить общее изложение. Дальнейшее обсуждение этого вопроса приводится в следующих частях книги.