- •7.7.6. Определить общее количество поставщиков
- •7.7.7. Определить в поставках максимальное
- •7.7.8. Для каждой поставляемой детали указать номер и общий объем поставки в штуках
- •7.7.9. Указать номера всех типов деталей, поставляемых более чем одним поставщиком
- •7.7.10. Определить имена поставщиков детали с номером т2'
- •7.7.11. Определить имена поставщиков по крайней мере одной красной детали
- •7.7.12. Указать номера поставщиков, статус которых меньше текущего максимального статуса
- •7.7.13. Указать имена поставщиков детали с номером 'р2'
- •7.7.14. Выбрать имена поставщиков, которые не поставляют деталь с номером 'р2'
- •7.7.15. Определить имена поставщиков всех типов деталей
- •7.7.16. Определить номера деталей, которые либо весят более 16 фунтов, либо поставляются поставщиком с номером 's2', либо и то, и другое
- •7.8. Резюме
- •8.2. Ограничения типа
- •8.3. Ограничения атрибута
- •8.4. Ограничения переменной-отношения
- •8.5. Ограничения баз данных
- •8.6. "Золотое правило"
- •8.7. Ограничения состояния и ограничения перехода
- •8.8. Ключи
- •3. Пусть r1 и r2 — ссылающаяся и ссылочная переменные-отношения соответственно.
- •8.9. Средства языка sql
- •8.10. Резюме
- •9.1. Введение
- •9.2. Для чего нужны представления
- •9.3. Выборка данных из представлений
- •9.4. Обновление данных в представлениях
- •9.5. Моментальные снимки
- •9.6. Поддержка представлений в языке sql
- •9.7. Резюме
- •Часть III
- •10.1. Введение
- •10.2. Основные определения
- •10.3. Тривиальные и нетривиальные зависимости
- •10.4. Замыкание множества зависимостей
- •10.5. Замыкание множества атрибутов
- •10.6. Неприводимые множества зависимостей
- •10.7. Резюме
- •Глава 1 1
- •I Переменные-отношения в знф I
- •11.2. Декомпозиция без потерь
- •11.3. Первая, вторая и третья нормальные формы
- •11.4. Сохранение зависимостей
- •11.5. Нормальная форма Бойса-Кодда
- •11.6. Замечание по поводу атрибутов, содержащих в качестве значений отношения
- •11.7. Резюме
- •12.1. Введение
- •12.2. Многозначные зависимости и четвертая нормальная форма
- •12.3. Зависимости соединения и пятая нормальная форма
- •Соединение по комбинации атрибутов j#,s#
- •Исходное состояние spj
- •12.4. Общая схема процедуры нормализации
- •12.5. Денормализация
- •12.6. Ортогональное проектирование (небольшое отступление от темы)
- •12.7. Другие нормальные формы
- •12.8. Резюме
- •12.3. Brosda V., Vossen g. Update and Retrieval Through a Universal Schema Interface // acm tods. — December, 1988. — 13, № 4.
- •12.5. Date c.J. Will the Real Fourth Normal Form Please Stand Up? // c. J. Date and Hugh Darwen. Relational Database Writings 1989-1991.— Reading, Mass.: Addison-Wesley, 1992.
- •12.20.Kent w. The Universal Relation Revisited // acm tods. — December, 1983. — 8, № 4.
- •12.22.Maier d., Ullman j.D. Fragments of Relations // Proc. 1983 sigmod Intern. Conf. On Management of Data. — San Jose, Calif. — May, 1983.
- •12.24.Maier d., Ullman j.D. Maximal Objects and the Semantics of Universal Relation Databases // acm tods. — March, 1983. — 8, № 1.
- •Глава 13
- •13.1. Введение
- •13.2. Общий подход
- •Каждыи экземпляр сущности ности «Произведение"
- •13.3. Модель "сущность/связь"
- •13.5. Проектирование базы данных с помощью метода er-моделирования
- •13.6. Краткий анализ er-модели
- •13.7. Резюме
7.7.16. Определить номера деталей, которые либо весят более 16 фунтов, либо поставляются поставщиком с номером 's2', либо и то, и другое
SELECT P.Pt
FROM Р
WHERE P.WEIGHT > 16.0 UNION
SELECT SP.Pt
FROM SP
WHERE SP.St = 'S2' ;
Лишние повторяющиеся строки всегда исключаются из результата выполнения не-уточненных операторов ONION, INTERSECT и EXCEPT (в языке SQL оператор EXCEPT служит аналогом операции MINUS реляционной алгебры). Однако язык SQL также поддерживает уточненные варианты этих операторов (UNION ALL, INTERSECT ALL и EXCEPT ALL), при которых повторяющиеся строки (если они есть) сохраняются. Примеры с этими вариантами операторов умышленно опускаются.
В заключение отметим, что, хотя список примеров операций выборки был достаточно большим, о многих возможностях языка SQL здесь даже не упоминалось. Язык SQL в действительности является чрезвычайно избыточным [4.18] в том смысле, что почти всегда существует множество способов формулирования одного и того же запроса и нам не хватит места, чтобы описать все возможные формулировки и все возможные опции даже для сравнительно небольшого числа примеров, которые приводились в этой главе.
7.8. Резюме
В этой главе кратко рассматривалось реляционное исчисление, альтернативное реляционной алгебре. Внешне два подхода очень отличаются: исчисление имеет описательный характер, тогда как характер алгебры — предписывающий, но на более низком уровне они представляют собой одно и то же, поскольку любые выражения исчисления могут быть преобразованы в семантически эквивалентные выражения алгебры и наоборот.
Реляционное исчисление существует в двух версиях: исчисление кортежей и исчисление доменов. Основное различие между ними состоит в том, что переменные исчисления кортежей изменяются на отношениях, а переменные исчисления доменов изменяются на доменах.
Выражение исчисления кортежей состоит из прототипа кортежа и необязательного предложения WHERE, содержащего логическое выражение или формулу WFF ("правильно построенную формулу"). Подобная формула WFF может включать кванторы (EXISTS и F0RALL), свободные и связанные ссылки на переменные, логические (булевы) операторы (AND, OR, NOT и др.) и т.д. Каждая свободная переменная, которая встречается в формуле WFF, также должна быть упомянута в прототипе кортежа.
Замечание. В настоящей главе явно этот вопрос не затрагивался, но выражения реляционного исчисления предназначены, по существу, для тех же целей, что и выражения реляционной алгебры (см. раздел 6.6 главы 6).
На примере было показано, как алгоритм редукции Кодда может использоваться для преобразования произвольного выражения реляционного исчисления в эквивалентное выражение реляционной алгебры, таким образом подготавливая почву для выбора возможной стратегии реализации исчисления. Вновь обратившись к вопросу реляционной полноты, мы кратко обсудили, каким образом можно доказать, что некоторый язык L является полным в этом смысле.
Кроме того, здесь обсуждалось, как можно расширить исчисление кортежей с целью поддержки определенных вычислительных возможностей (аналогичные возможности в реляционной алгебре обеспечиваются операциями EXTEND и SUMMARIZE). Затем читателям было представлено краткое введение в исчисление доменов и отмечено (правда, без попытки доказать это), что оно также является реляционно полным. Таким образом, исчисление кортежей, исчисление доменов и реляционная алгебра эквивалентны.
И наконец, вашему вниманию был представлен обзор соответствующих средств языка SQL. Язык SQL является своеобразной смесью реляционной алгебры и исчисления (кортежей). Например, в нем есть прямая поддержка таких операций реляционной алгебры, как соединение и объединение, но одновременно с этим используются переменные кортежей и квантор существования из реляционного исчисления. SQL-запрос представляет собой табличное выражение. Обычно такая конструкция содержит единственное выражение выборки, однако поддерживаются и различные типы явных выражений операций соединения (JOIN), причем выражения соединения и выборки могут комбинироваться произвольным образом с помощью операторов ONION, INTERSECT и EXCEPT. Также упоминалось о возможности использования предложения ORDER BY для определения упорядоченности строк в таблице, являющейся результатом вычисления данного табличного выражения (любого вида).
В частности, были описаны следующие компоненты выражений выборки.
Базовое предложение SELECT, в том числе использование ключевого слова DISTINCT, скалярных выражений, введение имен результирующих столбцов и использование предложения SELECT *
Предложение FROM, включая использование переменных кортежей
Предложение WHERE, включая использование оператора EXISTS
Предложения GROUP BY и HAVING, включая использование обобщающих функций COUNT, SUM, AVG, МАХ и MIN
Использование подзапросов в предложениях SELECT, FROM и WHERE
Кроме того, здесь был описан концептуальный алгоритм вычисления (т.е. схема формального определения) для выражений выборки.
Упражнения
7.1. Пусть р(х) и q — произвольные формулы WFF, в которых переменная х соответствен- но используется и не используется в качестве свободной переменной. Какие из сле- дующих формулировок верны? (Здесь символ "=>" означает "следует", а символ "=" оз- начает "эквивалентно". Обратите внимание, что если А => В и В => А, то А н В.)
а) EXISTS х ( q ) s q
б) FORALL х ( q ) = q
в) EXISTS x ( p (x) AND q ) = EXISTS x ( p (x) ) AND q r) FORALL x ( p (x) AND q ) = FORALL x ( p (x) ) AND q д) FORALL x ( p (x) ) => EXISTS x ( p (x) )
7.2. Пусть p(x,y) — это произвольная формула WFF со свободными переменными х и у. Какие из следующих формулировок верны?
а) EXISTS х EXISTS у ( р(х,у) ) = EXISTS у EXISTS х ( р(х,у) )
б) FORALL х FORALL у ( р(х,у) ) н FORALL у FORALL х ( р(х,у) )
в) FORALL х ( р(х,у) ) = NOT EXISTS х ( NOT р(х,у) )
г) EXISTS х ( р(х,у) ) з NOT FORALL X ( NOT р(х,у) )
д) EXISTS х FORALL у ( p(x,y) ) = FORALL у EXISTS x ( p(x,y) )
е) EXISTS у FORALL x ( p(x,y) ) => FORALL x EXISTS у ( p(x,y) )
7.3. Пусть pjx) и q(y) — произвольные формулы WFF со свободными переменными х и у соответственно. Какие из следующих формулировок верны?
а) EXISTS х ( р(х) ) AND EXISTS у ( q(y) ) = EXISTS х EXISTS у ( p(x) AND q(y) )
б) EXISTS x j IF p(x) THEN q(x) END IF ) s
IF FORALL x ( p(x) ) THEN EXISTS x ( q(x) ) END IF
7.4. Еще раз обратимся к запросу из примера 7.3.8: "Определить номера поставщи- ков по крайней мере всех типов деталей, поставляемых поставщиком с номером 'S2'". Для этого запроса возможна следующая формулировка в терминах исчис- ления кортежей.
SX.St WHERE FORALL SPY ( IF SPY.St = 'S2' THEN
EXISTS SPZ ( SPZ.SI = SX.St AND SPZ.Pt = SPY.Pt )
END IF )
(Здесь SPZ — это еще одна переменная кортежа, изменяющаяся на отношении поставок.) Что будет возвращено при выполнении этого запроса, если поставщик с номером 'S2' в данный момент не поставляет никаких деталей? Что будет, если в приведенном выражении переменную SX всюду заменить переменной SPX?
7.5. Вот пример запроса к базе данных поставщиков, деталей и проектов (используются обычные упрощения для имен переменных).
( PX.NAME, PX.CITY ) WHERE FORALL SX FORALL JX EXISTS SPJX
( SX.CITY = 'London' AND JX.CITY = 'Paris' AND SPJX.St = SX.St AND SPJX.Pt = PX.Pt AND SPJX.Jt = JX.Jt AND SPJX.QTY < QTY ( 500 ) )
а) Сформулируйте этот запрос в словесной форме.
б) Возьмите на себя роль СУБД и выполните этот запрос по предложенному Код- дом алгоритму редукции. Можете ли вы указать какие-либо улучшения, кото- рые целесообразно внести в данный алгоритм?
Выразите в терминах исчисления кортежей запрос "Получить три самые тяжелые детали".
Рассмотрим отношение спецификации материалов переменной-отношения PART_STRUCTURE, представленной в главе 4. (Соответствующие SQL-определения даны в ответе к упр. 4.6, а пример значения приведен на рис. 4.6.) Обратимся к широкоизвестному запросу разузлования деталей "Получить номера деталей, которые на любых уровнях вхождения являются компонентами некоторой заданной детали (скажем, детали с номером 'Р1')". Результат этого запроса, например от
ношение PART_LIST (которое, безусловно, является отношением, производным от исходного отношения PART_STRUCTURE), нельзя сформулировать в виде единственного выражения начального реляционного исчисления (или реляционной алгебры). Иначе говоря, производное отношение PART_LIST не может быть получено с помощью единственного выражения начального реляционного исчисления (или реляционной алгебры). Почему?
Предположим, что переменную-отношение поставщиков S заменили набором переменных-отношений LS, PS, AS... по одной переменной-отношению для каждого города (например, переменная-отношение LS будет содержать кортежи только для поставщиков из Лондона). Предположим также, что неизвестно, какие именно существуют города, в которых находятся поставщики, и поэтому неизвестно, сколько имеется таких переменных-отношений. Рассмотрим запрос "Существует ли в базе данных поставщик с номером 'S1'?". Можно ли такой запрос выразить в терминах исчисления (или алгебры)? Обоснуйте свой ответ.
Покажите, что язык SQL является реляционно полным.
Существуют ли в языке SQL эквиваленты реляционных операторов EXTEND и SUMMARIZE?
Существуют ли в языке SQL эквиваленты операторов реляционных сравнений?
Приведите как можно больше различных формулировок на языке SQL для запроса "Выбрать имена поставщиков детали с номером 'Р2"\
Упражнения по запросам
В основу всех остальных упражнений была положена база данных поставщиков, деталей и проектов (см. рис. 4.5 в главе 4 и ответ к упр. 5.4 в главе 5). В каждом случае вам будет предложено записать выражение, позволяющее выполнить указанный запрос. (В качестве интересной вариации попытайтесь сформулировать постановку той или иной задачи, глядя на ее ответ.)
Дайте ответы к упр. 6.13—6.50 в терминах исчисления кортежей.
Дайте ответы к упр. 6.13-6.50 в терминах исчисления доменов.
Дайте ответы к упр. 6.13-6.50, используя средства языка SQL.
Список литературы
В дополнение к приведенному ниже списку обратитесь также к [4.7], где описывается несколько расширений языка SQL, предназначенных для работы с транзитивным замыканием и другими подобными операциями. Эти расширения очень напоминают соответствующие возможности, предусмотренные стандартом SQL3, которые кратко описываются в приложении Б. По вопросу внедрения подобных средств в реляционное исчисление обратитесь к главе 23.
7.1. Codd E.F. A Data Base Sublanguage Founded on the Relational Calculus // Proc. 1971 ACM SIGFIDET Workshop on Data Description, Access and Control. — San Diego, Calif. —November, 1971.
Date C.J. A Note on the Relation Calculus // ACM SIGMOD Record 18. — 1989. — № 4. Переиздано: An Anomaly in Codd's Reduction Algorithm // Relational Database Writings 1989-1991. Reading, Mass.: Addison-Wesley, 1992.
Date C.J. Why Quantifier Order Is Important // C.J. Date and Hugh Darwen. Relational Database Writings 1989-1991. — Reading, Mass.: Addison-Wesley, 1992.
Date C.J. Relational Calculus as an Aid to Effective Query Formulation // C.J. Date and Hugh Darwen. Relational Database Writings 1989-1991.— Reading, Mass.: Addison-Wesley, 1992.
Почти все представленные на рынке современные реляционные продукты поддерживают язык SQL, а не реляционное исчисление (или реляционную алгебру). В этой статье, тем не менее, отстаивается (и иллюстрируется) применение реляционного исчисления как промежуточного шага в построении "сложных" SQL-запросов.
7.5. Held G.D., Stonebraker M.R., and Wong E. INGRES — A Relational Data Base System // Proc. NCC 44. — Anaheim, Calif. Montvale, N.J.: AFIPS Press, May, 1975.
С середины и до конца 70-х годов разрабатывались два главных реляционных прототипа: система System R в фирме IBM и система INGRES в Калифорнийском университете в Беркли. Оба эти проекта имели очень большое значение в исследовательском мире и впоследствии лидировали среди коммерческих систем как СУБД DB2 (в случае системы System R) и как коммерческий продукт INGRES (в случае системы INGRES).
Замечание. Прототип INGRES иногда называют "университетским INGRES" [7.11], чтобы отличать его от коммерческой версии этой системы. Учебный обзор коммерческой версии можно найти в [1.5].
Система INGRES вначале не являлась SQL-системой, поскольку исходно поддерживала язык QUEL (Query Language), который во многих отношениях технически превосходил SQL. В самом деле, язык QUEL по-прежнему составляет основу достаточного числа современных исследований баз данных, а примеры на языке QUEL до сих пор появляются в исследовательской литературе. Данная статья, в которой впервые был описан прототип INGRES, включает предварительное определение языка QUEL. См. также [7.10]-[7.12].
Kuhns J.L. Answering Questions by Computer: A Logical Study // Report RM-5428-PR, Rand Corp. — Santa Monica, Calif., 1967.
Lacrorix M., Pirotte A. Domain-Oriented Relational Languages // Proc. 3rd Int. Conf. on Very Large Data Bases. — Tokyo, Japan., October, 1977.
Merrett Т.Н. The Extended Relational Algebra, A Basis for Query Languages // Shneiderman B. (ed.). Databases: Improving Usability and Responsiveness. New York, N.Y.: Academic Press., 1978.
Назначением этой статьи является введение кванторов в алгебру — не просто кванторов существования и кванторов всеобщности реляционного исчисления, а более общих кванторов "количество" и "соотношение". С их помощью можно выразить такие условия, как "по крайней мере три", "не более половины", "нечетное число" и т.д.
7.9. Negri М., Pelagatti G., Sbattella L. Formal Semantics of SQL Queries // ACM TODS. — September, 1991.— 16, № 3.
Цитата из резюме: "Семантика SQL-запросов формально определена с помощью набора правил, определяющих преобразование на основе синтаксиса SQL-запроса в формальную модель, называемую расширенным исчислением трехзначных предикатов (Extended Three Valued Predicate Calculus— E3VPC), которая большей частью основана на хорошо известных математических понятиях. Приведены также правила преобразования общего выражения E3VPC в каноническую форму; [дополнительно] полностью решены проблемы, подобные анализу эквивалентности SQL-запросов". Однако отметим, что рассматриваемый здесь диалект языка SQL— это только первая версия стандарта (SQL/86), а не стандарт SQL/92.
7.10. Stonebraker М. The INGRES Papers: The Anatomy of a Relational Database Management System // Reading, Mass.: Addison-Wesley, 1986.
Собрание некоторых наиболее важных документов университетского проекта INGRES под редакцией одного из первых создателей этого проекта. (В собрание включены статьи [7.11], [7.12].) Насколько известно автору настоящей книги, это единственное доступное издание, в котором подробно описываются проект и реализация полномасштабной реляционной СУБД. Весьма ценный материал для серьезных студентов.
7.11. Stonebraker М., Wong Е., Kreps P., Held G. The Design Implementation of INGRES // ACM TODS. — September, 1976. — 1, № 3. (Переиздано [7.10].)
Подробное описание университетского прототипа INGRES.
7.12. Stonebraker М. Retrospection on a Data Base System // ACM TODS. — 1980. — 5, № 2. (Переиздано [7.10].)
Доклад по истории проекта прототипа INGRES (до января 1979 года). Акцент сделан скорее на ошибках и полученных уроках, чем на успехах.
7.13. Ullman J. D. Principles of Database and Knowledge-Base Systems: Volume I. Rockville, Md.: Computer Science Press, 1988.
Книга Ульмана, в отличие от данной книги, содержит более формальное изложение реляционного исчисления и связанных с ним вопросов. В частности, в ней обсуждается понятие безопасности выражений исчисления. Это имеет значение при адаптации немного измененной версии исчисления, в которой переменные кортежей не определяются отдельными операторами RANGE, а связываются с областью значений посредством явных условий в предложении WHERE. В такой версии исчисления запрос "Получить имена всех поставщиков из Лондона", например, может выглядеть так.
SX WHERE SX е S AND SX.CITY = 'London'
Одна из проблем, возникающих при использовании этой версии исчисления, заключается в том, что в ней недопустимы запросы, подобные следующему.
SX WHERE NOT ( SX е S )
Такие выражения называются небезопасными, так как они не возвращают конечный результат (множество всего, что не входит в отношение S, бесконечно). Поэтому необходимо ввести некоторые правила, обеспечивающие безопасность в
этом смысле, В книге Ульмана описаны такие правила (для исчисления как кортежей, так и доменов). Следует отметить, что в оригинальном исчислении Кодда такие правила были.
7.14. Zloof М. М. Query By Example // Proc. NCC 44.— Anaheim, Calif., 1975.— Montvale, N.J.: AF1PS Press, 1977.
Описанный в этой работе реляционный язык Query-By-Example (QBE) включает элементы исчисления кортежей и в еще большей степени — элементы исчисления доменов. Привлекательный и интуитивно понятный синтаксис языка основывается на идее формирования элементов в "шаблонные таблицы" на экране дисплея вместо записи линейных операторов. Например, формулировка языка QBE для запроса "Получить имена поставщиков по крайней мере одной детали, поставляемой поставщиком с номером 'S2'" (довольно сложный запрос) может выглядеть следующим образом.
S |
Si |
SNAME |
SP |
Si |
р# |
SP |
Si |
Pi |
|
SX |
P. NX |
|
SX |
PX |
|
S2 |
PX |
Пояснение. Пользователь обращается к системе с запросом отобразить на экране три шаблонные таблицы (одну — для отношения S и две — для отношения SP), после чего формирует в них элементы, как показано выше. Элементы, начинающиеся символом подчеркивания, представляют "образцы" (т.е. переменные доменов); остальные элементы представляют собой литералы. В этом случае пользователь обращается к системе с запросом "предоставить" ("Р") значения имен поставщиков ( NX), таких, что если это поставщик _SX, то _SX поставляет некоторую деталь _РХ, а деталь _РХ, в свою очередь, также поставляется поставщиком с номером 'S2'. Заметьте, что под кванторами существования подразумевается (как, кстати, и под кванторами существования в языке QUEL) совсем другой смысл, поэтому данный синтаксис прост для понимания.
Вот другой пример: "Определить все пары номеров поставщиков, которые находятся в одном городе".
S |
si |
CITY |
|
|
|
|
SX |
CZ |
P. |
_SX |
_SY |
|
~SY |
~CZ |
|
|
|
К сожалению, язык QBE не является реляционно полным, а конкретнее — не поддерживает (в полной мере) негативный квантор существования (NOT EXISTS). Вследствие этого определенные запросы (например, "Получить имена поставщиков всех типов деталей") не могут быть выражены в языке QBE. (На самом деле язык QBE вначале "поддерживал" квантор NOT EXISTS, по крайней мере неявно, но построение всегда было сопряжено с некоторыми трудностями. Основная проблема заключалась в том, что не было способа указать порядок, в котором различные неявные кванторы могли бы быть применены, а этот порядок, к сожалению, очень важен; см. [7.3] или ответ к упр. 7.2. Поэтому определенные запросы получались неоднозначными [7.3].)
Злуф (автор этой работы) первым изобрел и разработал язык QBE. Данная статья была первой из многих статей, написанных Злуфом по этой тематике.
Ответы к некоторым упражнениям
7.1. а) верно; 6) верно; в) верно; г) верно; д) не верно.
Замечание. Причина, по которой утверждение д не верно, состоит в том, что применение квантора FORALL к пустому множеству всегда дает значение истина. И наоборот, применение квантора EXISTS к пустому множеству всегда дает значение ложь. Поэтому, например, если утверждение "Все фиолетовые детали весят более 100 фунтов" истинно, то это необязательно означает, что действительно существуют фиолетовые детали.
Заметим, что тождества (верные!) могут использоваться в качестве основы для множества правил преобразования выражений исчисления аналогично алгебраическим правилам преобразования, упоминавшимся в главе 6 и подробно обсуждающимися в главе 17. Аналогичные замечания также применимы к упр. 7.2 и 7.3.
7.2. а) верно; б) верно; в) верно (этот пример рассматривался в основном тексте главы); г) верно (следовательно, один квантор может быть определен через другой); д) не верно; е) верно. Обратите внимание, что последовательность одинаковых кванторов — как в тождествах а и б — может быть записана в лю- бом порядке без изменения смысла выражения, тогда как для разных кванто- ров — как показано в тождестве д — такой порядок имеет существенное зна- чение. Чтобы проиллюстрировать последнее, предположим, что переменные х и у изменяются на множестве целых чисел и р является формулой WFF у > х. Очевидно,что формула
FORALL х EXISTS у ( у > х )
("для всех целых х существует целое у, большее х") дает значение истина, тогда как формула
EXISTS у FORALL X (у > X )
("существует целое у, большее любого целого х") дает значение ложь. Таким образом, перестановка неодинаковых кванторов изменяет значение выражения. Поэтому в языке запросов, основанном на реляционном исчислении, перестановка неодинаковых кванторов в предложении WHERE изменяет значение запроса [7.3].
а) верно; б) верно.
Если поставщик с номером 'S2' в данный момент не поставляет никаких деталей, исходный запрос будет возвращать все номера поставщиков из отношения S (включая, в частности, самого поставщика с номером 'S2', сведения о котором согласно нашему предположению содержатся в отношении S, но отсутствуют в SP). Если везде заменить переменную SX переменной SPX, то запрос будет возвращать все номера поставщиков, содержащихся в отношении SP. Различие между двумя формулировками следующее: первая означает "Получить номера поставщиков всех типов деталей, поставляемых поставщиком с номером 'S2'" (что и требуется), а вторая — "Получить номера поставщиков по крайней мере одной детали и по крайней мере всех типов деталей, которые поставляются поставщиком с номером 'S2'".
а) Получить наименование детали и название города для деталей, поставляемых для каждого проекта в Париже каждым поставщиком в Лондоне в количестве менее 500 штук, б) Результат выполнения этого запроса — пустое множество.
Это упражнение очень трудное! Особенно если мы будем учитывать, что вес деталей неуникален. (Если бы их вес был уникален, можно было бы переформулировать запрос так: "Получить все детали, такие, что количество более тяжелых деталей меньше трех".) Упражнение настолько трудное, что мы даже не пытаемся дать здесь полное решение на языке реляционного исчисления. Оно очень хорошо иллюстрирует тот факт, что реляционная полнота является лишь основным критерием выразительной силы языка, но необязательно достаточным. (Следующие два примера также иллюстрируют этот момент.) Подобные запросы обсуждаются в [6.4].
Пусть PSA, PSB, PSC, PSn— переменные кортежей, изменяющиеся на переменной-отношении PART_STRUCTURE. Предположим также, что заданная деталь — это деталь с номером 'Р1'. Тогда имеем следующее.
а) Выражение реляционного исчисления для запроса "Получить номера деталей для всех типов деталей, которые являются компонентами детали с номером 'р1' на первом уровне входимости" будет таким.
PSA.MIN0R_Pi WHERE PSA.MAJOR_Pt = Р ( 'PI' )
б) Выражение реляционного исчисления для запроса "Получить номера деталей для всех деталей, которые являются компонентами детали с номером 'р1' на втором уровне входимости" будет таким.
PSB.MINOR Pt WHERE EXISTS PSA
( PSA.MAJOR PI = P ( 'PI' ) AND PSB.MAJOR~P| = PSA.MINOR_P| )
в) Выражение реляционного исчисления для запроса "Получить номера деталей для всех деталей, которые являются компонентами детали с номером 'р1' на третьем уровне входимости" будет таким.
PSC.MINOR_Pt WHERE EXISTS PSA EXISTS PSB
( PSA.MAJOR_P| = P ( 'PI' ) AND PSB.MAJOR_Pl = PSA.MINOR_Pl AND PSC.MAJOR_Pi = PSB.MINOR_Pl )
И т.д. Выражение реляционного исчисления для запроса "Получить номера деталей для всех деталей, которые являются компонентами детали с номером 'р1' на и-м уровне входимости" будет таким.
PSn.MINOR_Pf WHERE EXISTS PSA EXISTS PSB ... EXISTS PS(fl-l) ( PSA.MAJOR_Pi = P ( 'PI' ) AND PSB.MAJOR_Pf = PSA.MINOR_Pf AND PSC.MAJOR~Pf = PSB.MINOR~Pt AND
7.. AND
PSn.MAJOR_Pf = PS(fl-l).MINOR_Pt )
Для построения отношения PMT_LIST все результирующие отношения из пп. а, б,в,...,п необходимо объединить.
Проблема заключается в том, что невозможно записать п таких выражений, если значение п неизвестно. Следовательно, запрос разузлования детали является классической иллюстрацией задачи, которая не может быть сформулирована с помощью отдельных выражений на языке, обладающем лишь свойством реляционной полноты, т.е. на языке, который не является более мощным, чем реляционное исчисление (или алгебра). Частично эту проблему можно решить с помощью оператора TCL0SE, кратко рассмотренного в главе 6 (но только частично). Дальнейшие подробности выходят за рамки этой книги.
Замечание. Хотя данную задачу обычно называют составлением спецификации материалов или разузлованием деталей, применяется она на самом деле значительно шире, чем можно судить по этим названиям. В действительности класс отношений вида "детали содержат детали" очень широко распространен в самых разных приложениях. Кроме всего прочего, подобный вид отношений присутствует в процессах управления иерархическими структурами, в родословных деревьях, графах аутентификации, сетевых взаимодействиях, структурах вызова программных модулей, транспортных сетях и т.д.
7.8. Этот запрос нельзя выразить ни в терминах исчисления, ни в терминах алгебры. Например, чтобы выразить его в терминах исчисления, по существу, потребова- лось бы уметь выражать нечто подобное следующему.
"Существует ли отношение г, такое, что в этом отношении г имеется кортеж t, такой, что t.SI = Si ( 'SI' )?"
Другими словами, мы должны были бы уметь квалифицировать отношения, а не кортежи и, следовательно, потребовалась бы иная переменная с новой областью значений, т.е. такая переменная, значениями которой являлись бы некоторые отношения, а не кортежи. Поэтому подобный запрос не может быть выражен в терминах реляционного исчисления, как оно определено на настоящий момент.
Кстати, обратите внимание, что рассматриваемый запрос — это запрос типа "Да — нет" (причем, желаемый ответ — чаще всего значение истина). Поэтому читателю может показаться, что запрос нельзя выразить в терминах исчисления или с помощью алгебры, потому что выражения реляционного исчисления и алгебры принимают значения отношений, а не логические. Однако запросы типа "Да — нет" могут быть выражены в терминах исчисления и алгебры, если они правильно реализованы! Главная трудность заключается в том, чтобы понять, что результаты "да" и "нет" (эквивалентные значениям истина и ложь) могут быть представлены как отношения. Рассматриваемые отношения — это TABLE_DEE и TABLE DUM соответственно. Более подробное обсуждение этих отношений приводится в [5.5].
7.9. Для подтверждения реляционной полноты языка SQL необходимо сначала пока- зать, что существуют SQL-выражения для каждой из пяти примитивных операций реляционной алгебры (выборки, проекции, произведения, объединения и вычита- ния), а затем доказать, что операнды таких SQL-выражений могут, в свою очередь, быть произвольными выражениями языка SQL.
Начнем с предварительного замечания о том, что язык SQL фактически поддерживает оператор переименования реляционной алгебры RENAME после введения в стандарт SQL/92 необязательной спецификации AS <иш столбца> в предложении SELECT. Следовательно, можно быть уверенным, что все имена столбцов в таблицах правильны и, в частности, что операнды операций произведения, объединения и вычитания удовлетворяют требованиям реляционной алгебры (в нашей версии) в отношении именования столбцов. Более того, указанные требования к именованию столбцов операндов действительно удовлетворяются: правила вывода имен столбцов в языке SQL фактически совпадают с аналогичными правилами реляционной алгебры (в нашей версии), что было показано в главе 6.
Вот выражения языка SQL, соответствующие пяти примитивным операциям алгебры. Алгебра Язык SQL
A WHERE р
А {X, у,..., Z}
A TIMES В A UNION В A MINUS В
SELECT * FROM A WHERE р
SELECT DISTINCT X, y,...,Z FROM A
A CROSS JOIN В
SELECT * FROM A UNION SELECT * FROM В SELECT * FROM A EXCEPT SELECT * FROM В
Обратившись к грамматике табличных выражений языка SQL, которая описывается в приложении А, можно увидеть, что переменные А и В в приведенных выше SQL-выражениях по сути являются значениями параметра <ссылка на таблицу>. Можно убедиться еще и в том, что если заключить каждое из пяти показанных SQL-выражений в скобки, то оно также станет допустимым значением этого же параметра7. Отсюда следует, что язык SQL на самом деле является реляционно полным.
Замечание. В действительности во всем вышесказанном есть один недостаток: язык SQL не поддерживает проекций по нулевому количеству столбцов (поскольку он не поддерживает пустых предложений SELECT). Как следствие язык SQL не поддерживает таблиц TABLE_DEE и TABLE_DUM [5.5].
7.10. Язык SQL поддерживает операцию EXTEND, но не SUMMARIZE (по крайней мере, не непосредственно). Что касается операции EXTEND, то выражение реляционной алгебры
EXTEND A ADD ехр AS Z
в языке SQL может быть представлено так.
SELECT A.*, exp' AS Z FROM ( А ) AS А
7 Здесь мы игнорируем mom факт, что в языке SQL параметр <ССЫЛКа на таблицу> в действительности требует включения в свое значение определения переменной кортежа с пустой областью значений (см. приложение А).
Выражение ехр' в предложении SELECT является SQL-аналогом операнда ехр в выражении EXTEND. Заключенная в скобки ссылка на переменную А представляет собой значение параметра <ссылка на та6пицу> произвольной сложности
(соответствующую операнду А оператора EXTEND). Вторая ссылка А в предложении FROM — имя переменной кортежа.
Что касается операции SUMMARIZE, основная проблема состоит в том, что выражение реляционной алгебры
SUMMARIZE A PER В ...
возвращает результат, кардинальность которого равна кардинальности операнда В, в то время как "эквивалентное" этой функции SQL-выражение
SELECT ... FROM А GROUP BY С ;
возвращает результат с кардинальностью, равной кардинальности проекции таблицы А по атрибуту С.
7.11. Язык SQL не поддерживает реляционных сравнений непосредственно. Однако по- добные операции можно смоделировать, хотя и в виде очень громоздких выраже- ний. Например, реляционное сравнение А = В (где А и В — отношения) можно ус- пешно смоделировать с помощью следующего SQL-выражения.
NOT EXISTS ( SELECT * FROM A
WHERE NOT EXISTS ( SELECT * FROM В
WHERE к-строка = В-строка ) )
Здесь операнды К-строка и В-строка— это значения параметра <конструктор строки> (приложение А), представляющие соответственно всю строку таблицы А и всю строку таблицы В.
7.12. Вот несколько таких формулировок. Заметьте, что этот список далеко не исчерпы- вающий [4.18]. Обратите внимание также на простоту каждого запроса!
SELECT DISTINCT S.SNAME FROM S WHERE S.St IN
( SELECT SP.St FROM SP
WHERE SP.Pt = 'P2' ) ;
SELECT DISTINCT T.SNAME
FROM ( S NATURAL JOIN SP ) AS T
WHERE T.Pt = 'P2' ;
SELECT DISTINCT T.SNAME
FROM ( S JOIN SP ON S.St = SP.Pt AND SP.Pt = 'P2' ) AS T ;
SELECT DISTINCT T.SNAME
FROM ( S JOIN SP USING St ) AS T
WHERE T.Pt = 'P2' ;
SELECT DISTINCT S.SNAME FROM S WHERE EXISTS ( SELECT * FROM SP
WHERE SP.Si = S.Sf AND SP.Pi = 'P2' ) ;
SELECT DISTINCT S.SNAME FROM S, SP WHERE S.SI = SP.Si AND SP.Pi = 'P2' ;
SELECT DISTINCT S.SNAME FROM S WHERE 0 <
( SELECT COUNT(*) FROM SP
WHERE SP.Si = S.SI AND SP.Pi = 'P2' ) ;
SELECT DISTINCT S.SNAME FROM S WHERE 'P2' IN
( SELECT SP.Pi FROM SP
WHERE SP.SI = S.St ) ; SELECT S.SNAME FROM S, SP WHERE S.St = SP.St AND SP.PI = 'P2' GROUP BY S.SNAME ;
Дополнительный вопрос. Каков смысл всех приведенных выше запросов?
7.13. Мы перенумеровали решения для этого пункта как ТЛЗ.п, где п — номер исходного упражнения в главе 6, т.е. упр. б.п. Подразумевается, что переменные SX, SY, РХ, PY, JX, JY, SPJX, SPJY и т.д. — это переменные кортежей, изменяющихся на отношениях S, Р, J и SPJ соответственно. Определение этих переменных кортежей в ответах не показано.
7.13.13. JX
7.13.14.JX WHERE JX.CITY = 'London'
7.13.15.SPJX.S# WHERE SPJX.Jt = Jl ( 'Jl' )
7.13.16.SPJX WHERE SPJX.QTY > QTY ( 300 ) AND SPJX.QTY < QTY ( 750 )
7.13.17. ( PX.COLOR, PX.CITY )
7.13.18. ( SX.Sf, PX.Pt, JX.Jt ) WHERE SX.CITY = PX.CITY
AND PX.CITY = JX.CITY AND JX.CITY = SX.CITY
7.13.19. ( SX.Sf, PX.Pt, JX.Jt ) WHERE SX.CITY * PX.CITY
OR PX.CITY Ф JX.CITY OR JX.CITY Ф SX.CITY
7.13.20. ( SX.Si, PX.Pt, JX.Jt ) WHERE SX.CITY Ф PX.CITY
AND PX.CITY Ф JX.CITY AND JX.CITY Ф SX.CITY
7.13.21.SPJX.Pf WHERE EXISTS SX ( SX.St = SPJX.St AND
SX.CITY = 'London' )
7.13.22.SPJX.Pf WHERE EXISTS SX EXISTS JX
{ SX.Sf = SPJX.St AND SX.CITY = 'London' AND JX.Jf = SPJX.Jf AND JX.CITY = 'London' )
7.13.23. ( SX.CITY AS SCITY, JX.CITY AS JCITY )
WHERE EXISTS SPJX ( SPJX.St = SX.St AND SPJX.Jf = JX.Jf )
7.13.24.SPJX.Pf WHERE EXISTS SX EXISTS JX
( SX.CITY = JX.CITY AND SPJX.St = SX.Sf AND SPJX.Jf = JX.Jt )
7.13.25.SPJX.Jf WHERE EXISTS SX EXISTS JX
( SX.CITY Ф JX.CITY AND SPJX.St = SX.Sf AND SPJX.Jf = JX.Jt )
7.13.26. ( SPJX.Pf AS XPf, SPJY.Pf AS YPf )
WHERE SPJX.St = SPJY.Sf AND SPJX.Pf < SPJY.Pf
7.13.27.COUNT ( SPJX.Jf WHERE SPJX.St = Si ( 'SI' ) ) AS N
7.13.28.SUM ( SPJX WHERE SPJX.St = St ( 'SI' )
AND SPJX.Pf = Pf ( 'Pi' ), QTY ) AS Q
Замечание. Следующее "решение" не верно (почему?).
SUM ( SPJX.QTY WHERE SPJX.St = St ( 'SI' )
AND SPJX.Pf = Pt ( 'PI' ), QTY ) AS Q
Ответ. При вычислении суммы повторяющиеся значения в столбце QTY буду: игнорироваться.
7.13.29. ( SPJX.Pf, SPJX.Jf,
SUM ( SPJY WHERE SPJY.Pf = SPJX.Pf
AND SPJY.Jf = SPJX.Jf, QTY ) AS Q )
7.13.30.SPJX.Pf WHERE
AVG ( SPJY WHERE SPJY.Pf = SPJX.Pf
AND SPJY.Jf = SPJX.Jf, QTY ) > QTY ( 350 )
7,13.31.JX.JNAME WHERE EXISTS SPJX ( SPJX.Ji = JX.Jl AND
SPJX.Si = S ( 'SI' ) )
7.13.32.PX.COLOR WHERE EXISTS SPJX ( SPJX.Pi = PX.Pi AND
SPJX.Si = Si ( 'SI' ) )
7.13.33.SPJX.Pi WHERE EXISTS JX ( JX.CITY = 'London' AND
JX.Ji = SPJX.Ji )
7.13.34.SPJX.Ji WHERE EXISTS SPJY ( SPJX.Pi = SPJY.Pi AND
SPJY.Si = Si ( 'SI' ) )
7.13.35.SPJX.Si WHERE EXISTS SPJY EXISTS SPJZ EXISTS PX , ( SPJX.Pi = SPJY.Pi AND SPJY.Si = SPJZ.S| AND SPJZ.Pi = PX.Pi AND PX.COLOR = COLOR ( 'Red' ) )
7.13.36.SX.Si WHERE EXISTS SY ( SY.Si = Si { 'SI' ) AND
SX.STATUS < SY.STATUS )
7.13.37.JX.Ji WHERE FORALL JY ( JY.CITY > JX.CITY ) или JX.Ji WHERE JX.CITY = MIN ( JY.CITY )
7.13.38.SPJX.Ji WHERE SPJX.Pi = Pi ( 'PI' ) AND
AVG ( SPJY WHERE SPJY.Pi = Pi ( 'PI' )
AND SPJY.Ji = SPJX.Ji, QTY ) > MAX ( SPJZ.QTY WHERE SPJZ.Ji = Ji ( 'Jl' ) )
7.13.39.SPJX.Si WHERE SPJX.Pi = Pi ( 'PI' ) AND SPJX.QTY > AVG ( SPJY
WHERE SPJY.Pi = Pi ( 'PI' ) AND SPJY.Ji = SPJX.Ji, QTY )
7.13.40.JX.Ji WHERE NOT EXISTS SPJX EXISTS SX EXISTS PX ( SX.CITY = 'London' AND PX.COLOR = COLOR ( 'Red' ) AND SPJX.Si = SX.Si AND SPJX.Pi = PX.Pi AND
SPJX.Ji = JX.Ji )
7.13.41.JX.Ji WHERE FORALL SPJY ( IF SPJY.Ji = JX.Ji
THEN SPJY.Si = Si ( 'SI' ) END IF j
7.13.42.PX.Pi WHERE FORALL JX
( IF JX.CITY = 'London' THEN EXISTS SPJY ( SPJY.Pi = PX.Pi AND SPJY.Ji = JX.Ji )
END IF )
7.13.43.SX.Si WHERE EXISTS PX FORALL JX EXISTS SPJY ( SPJY.Si = SX.Si AND
SPJY.Pi = PX.Pt AND SPJY.Jt = JX.Jt j
7.13.44.JX.Jt WHERE FORALL SPJY ( IF SPJY.St = Sf ( 'SI' ) THEN
EXISTS SPJZ ( SPJZ.Ji = JX.Jf AND SPJZ.Pf = SPJY.Pf ) END IF }
7.13.45.RANGEVAR VX RANGES OVER
( SX.CITY ), ( PX.CITY ), ( JX.CITY ) ;
VX.CITY
7.13.46.SPJX.Pf WHERE EXISTS SX ( SX.St = SPJX.St AND
SX.CITY = 'London' ) OR EXISTS JX ( JX.Jf = SPJX.Jf AND JX.CITY = 'London' )
7.13.47. ( SX.St, PX.Pt }
WHERE NOT EXISTS SPJX ( SPJX.St = SX.Sf AND
SPJX.Pf = PX.Pt )
7.13.48. ( SX.Sf AS XSt, SY.Sf AS YSf } WHERE FORALL PZ
( { IF EXISTS SPJX ( SPJX.St = SX.Sf AND
SPJX.Pf = PZ.Pf ) THEN EXISTS SPJY ( SPJY.Sf = SY.Sf AND SPJY.Pf = PZ.Pf )
END IF )
AND
( IF EXISTS SPJY ( SPJY.Sf = SY.Sf AND SPJY.Pf = PZ.Pf ) THEN EXISTS SPJX ( SPJX.St = SX.St AND SPJX.Pf = PZ.Pf )
END IF ) )
7.13.49.( SPJX.St, SPJX.Pf, ( SPJY.Jf, SPJY.QTY WHERE
SPJY.Sf = SPJX.St AND SPJY.Pf = SPJX.Pf ) AS JQ )
7.13.50. Пусть R — это результат вычисления выражения из ответа к предыдущему уп ражнению. Тогда имеем следующее.
RANGEVAR RX RANGES OVER R , RANGEVAR RY RANGES OVER RX.JQ ;
(RX.St, RX.Pf, RY.Jf, RY.QTY )
Мы несколько расширили синтаксис и семантику параметра <определени переменной кортежа>. Идея состоит в том, что определение переменной RY зави сит от переменной RX (обратите внимание на то, что оба определения разделеш запятыми, а не точками с запятыми, и поэтому связаны в одну операцию). Даль нейшее обсуждение этого вопроса приводится в [3.3].
7.14. Мы перенумеровали решения для этого пункта в виде 7Л4.п, где п— номер исходного упражнения в главе 6, т.е. упр. б.и. Относительно определения и именования переменных доменов будем следовать соглашениям, принятым в разделе 7.6.
7.14.13. ( JX, NAMEX, CITYX )
WHERE J ( Jf:JX, JNAME:NAMEX, CITY:CITYX )
7.14.14. ( JX, NAMEX, 'London' AS CITY )
WHERE J ( Jf:JX, JNAME:NAMEX, CITY:'London' )
7.14.15.SX WHERE SPJ ( S#:SX, J|:Jf ( 'Jl' ) )
7.14.16. ( SX, PX, JX, QTYX )
WHERE SPJ ( Sf:SX, P|:PX, Jf:JX, QTY:QTYX } AND QTYX > QTY ( 300 ) AND QTYX < QTY ( 750 )
( COLORX, CITYX WHERE P ( COLOR:COLORX, CITY:CITYX ) )
( SX, PX, JX ) WHERE EXISTS CITYX
{ S ( Si:SX, CITY:CITYX ) AND P ( Pl:PX, CITY:CITYX ) AND J ( Jl:JX, CITY:CITYX ) }
7.14.19. { SX, PX, JX )
WHERE EXISTS CITYX EXISTS CITYY EXISTS CITYZ { S ( Si:SX, CITY:CITYX ) AND P ( Pi:PX, CITY:CITYY ) AND J { Ji:JX, CITY:CITYZ ) AND ( CITYX Ф CITYY OR CITYY Ф CITYZ OR CITYZ Ф CITYX ) )
7.14.20. ( SX, PX, JX )
WHERE EXISTS CITYX EXISTS CITYY EXISTS CITYZ ( S ( Sl:SX, CITY:CITYX ) AND P { P#:PX, CITY:CITYY ) AND J ( J#:JX, CITY:CITYZ ) AND { CITYX Ф CITYY AND CITYY Ф CITYZ AND CITYZ Ф CITYX ) )
7.14.21.PX WHERE EXISTS SX ( SPJ ( P|:PX, S|:SX J AND
S ( Si:SX, CITY:'London' ) )
7.14.22.PX WHERE EXISTS SX EXISTS JX
( SPJ ( Si:SX, P#:PX, Ji:JX ) AND S ( Si:SX, CITY:'London' ) AND J ( J|:JX, CITY:'London' )
7.14.23. ( CITYX AS SCITY, CITYY AS JCITY ) WHERE EXISTS SX EXISTS JY
( S ( Si:SX, CITY:CITYX )
AND J ( Ji:JY, CITY:CITYY ) AND SPJ ( St:SX, J|:JY ) )
7.14.24.PX WHERE EXISTS SX EXISTS JX EXISTS CITYX ( S ( St;SX, CITYiCITYX ) AND J ( Ji-.JY, CITYtCITYX ) AND SPJ ( Si:SX, Pi:PX, Ji:JX ) )
7.14.25.JY WHERE EXISTS SX EXISTS CITYX EXISTS CITYY ( SPJ ( Si:SX, J|:JY ) AND S ( Sf:SX, CITY:CITYX } AND J ( Ji:JY, CITY:CITYY ) AND CITYX Ф CITYY )
7.14.26. { PX AS XP|, PY AS YPt ) WHERE EXISTS SX
{ SPJ ( S|:SX, PfiPX } AND SPJ ( St:SX, Pi:PY ) AND PX < PY )
7.14.27-7.14.30. Решения опущены.
7.14.31.NAMEX WHERE EXISTS JX
( J ( Jt:JX, JNAME:NAMEX ) AND SPJ ( S#:S# ( 'SI' ), Jt:JX ) )
7.14.32.COLORX WHERE EXISTS PX
( P ( Pt:PX, COLOR:COLORX ) AND SPJ { S#:S# { 'SI' ), PI:PX J )
7.14.33. PX WHERE EXISTS JX
( SPJ ( Pf:PX, Ji:JX ) AND J ( Ji:JX, CITY:'London' ) )
7.14.34.JX WHERE EXISTS PX
{ SPJ ( Pi:PX, Jl:JX ) AND SPJ ( P|:PX, Si:Si( 'SI' ) ) }
7.14.35. SX WHERE EXISTS PX EXISTS SY EXISTS PY
( SPJ ( Si:SX, Pi:PX ) AND
SPJ ( Pi-.PX, S#:SY ) AND
SPJ ( Si:SY, P#:PY ) AND
P ( Pi:PY, COLOR:COLOR ( 'Red' ) ) )
7.14.36. SX WHERE EXISTS STATUSX EXISTS STATUSY
{ S ( Sl:SX, STATUS:STATUSX ) AND S ( St:SI ( 'SI' ), STATUS:STATUSY J AND STATUSX < STATUSY )
7.14.37. JX WHERE EXISTS CITYX
{ J ( Jl:JX, CITY:CITYX ) AND FORALL CITYY ( IF J { CITY:CITYY } THEN CITYY > CITYX END IF) )
7.14.38-7.14.39. Решения опущены.
7.14.40. JX WHERE J ( Jt:JX ) AND
NOT EXISTS SX EXISTS PX
( SPJ ( Sf:SX, Pi:PX, Jt;JX ) AND S ( St:SX, CITY:'London' } AND P ( Pi:PX, COLOR:COLOR ( 'Red' ) ) )
7.14.41. JX WHERE J ( Ji:JX )
AND FORALL SX ( IF SPJ ( Sf:SX, Ji:JX ) THEN SX = Si ( 'SI' ) END IF )
7.14.42. PX WHERE P ( Pf:PX )
AND FORALL JX ( IF J ( J|:JX, CITY;'London' ) THEN SPJ ( Pi:PX, Ji:JX ) END IF )
7.14.43. SX WHERE S ( St:SX )
AND EXISTS PX FORALL JX
( SPJ ( Si:SX, P|:PX, J|:JX ) )
7.14.44. JX WHERE J ( J|:JX )
AND FORALL PX ( IF SPJ ( S|:Sl ( 'SI' ), Pt:PX ) THEN SPJ ( Pf:PX, Ji:JX ) END IF )
7.14.45.CITYX WHERE EXISTS S ( CITYtCITYX ) OR P ( CITY:CITYX )
OR J ( CITY:CITYX }
7.14.46.PX WHERE EXISTS SX ( SPJ ( Sl:SX, P|:PX ) AND
S ( Si:SX, CITY:'London' ) ) OR EXISTS JX ( SPJ ( Ji:JX, P|:PX ) AND
J ( Jt:JX, CITY:'London' ) )
7.14.47. ( SX, PX ) WHERE S ( Si:SX ) AND P ( Pi:PX )
AND NOT SPJ { Sl:SX, Pi:PX )
7.14.48. ( SX AS XSi, SY AS YSi )
WHERE S { Sl:SX ) AND S ( S|:SY ) AND FORALL PZ
( ( IF SPJ ( S|:SX, Pf:PZ ) THEN SPJ ( S|:SY, P|:PZ ) END IF ) AND
( IF SPJ ( Si:SY, P#:PZ ) THEN SPJ ( S#:SX, PfhPZ ) END IF ) )
7.14.49-7.14.50. Решения опущены.
7.15. Мы перенумеровали решения этого пункта в виде 7.15.и, что соответствует номерам 6.и в исходных упражнениях главы 6.
7.15.13. SELECT * FROM J ;
или просто
TABLE J ;
select from where
select from where
select from where and
select from
select from where and
select from where
select from where and and
select from where
7.15.22. select from where
and
7.15.23. select from where
j.* j
j.city = 'London' ;
distinct spj.Sf spj
spj.Ji = 'Jl' ;
spj. * spj
spj.qty >= 300 spj.qty <= 750 ;
distinct p.color, p.city p ;
s.SI, p.Pi, j.Ji s, p, j
s.city = p. city p.city = j. city ;
s.si, p.Pi, j.Ji
s, p, j
not ( s.city = p.city and p.city = j.city ) ;
S.si, p.Pi, J.Ji
s, p, j
s.city <> p.city p.city <> j.city j.city <> p.city ;
distinct spj.Pi spj
( select s.city from s
where s.SI = spj.Si ) = 'London' ;
distinct spj.Pi spj
( select s.city from s
where s.SI = spj.Si } = 'London' ( select j.city from j
where j.Ji = spj.Ji ) = 'London' ;
distinct s.city as scity, j.city as jcity s, j exists select * from spj
WHERE SPJ.St = AND SPJ.Jt =
S.Sf
J.Jt } ;
7.15.24. SELECT DISTINCT FROM SPJ WHERE ( SELECT
SPJ.Pf
S.CITY
FROM S
WHERE S.St = SPJ.St ) = { SELECT J.CITY FROM J
WHERE J.Jt = SPJ.Jt ) ;
7.15.25. SELECT FROM WHERE
DISTINCT SPJ
( SELECT
SPJ.Jt
S.CITY
FROM S
WHERE S.St = SPJ.St ) <> ( SELECT J.CITY FROM J
WHERE J.Jt = SPJ.Jt ) ;
7.15.26.SELECT DISTINCT SPJX.Pf AS PA, SPJY.Pf AS PB FROM SPJ AS SPJX, SPJ AS SPJY WHERE SPJX.St = SPJY.Sf AND SPJX.Pf < SPJY.Pf ;
7.15.27.SELECT COUNT ( DISTINCT SPJ.Jt ) AS N FROM SPJ
WHERE SPJ.St = 'SI' ;
7.15.28.SELECT SUM ( SPJ.QTY } AS X FROM SPJ WHERE SPJ.St = 'SI' AND SPJ.Pf = 'PI' ;
7.15.29.SELECT SPJ.Pf, SPJ.Jt, SUM ( SPJ.QTY ) AS Y FROM SPJ
GROUP BY SPJ.Pf, SPJ.Jt ;
7.15.30.SELECT DISTINCT SPJ.Pf FROM SPJ
GROUP BY SPJ.Pf, SPJ.Jt HAVING AVG ( SPJ.QTY ) > 350 ;
7.15.31.SELECT DISTINCT J.JNAME
FROM J, SPJ
WHERE J.Jt = SPJ.Jt
AND SPJ.St = 'SI' ;
7.15.32.SELECT DISTINCT P.COLOR FROM P, SPJ WHERE P.Pt = SPJ.Pf AND SPJ.St = 'SI' ;
7.15.33.SELECT DISTINCT SPJ.Pf FROM SPJ, J WHERE SPJ.Ji = J.Ji AND J.CITY = 'London' ;
7.15.34.SELECT DISTINCT SPJX.Ji
FROM SPJ AS SPJX, SPJ AS SPJY WHERE SPJX.Pi = SPJY.Pi AND SPJY.Si = 'SI' ;
7.15.35.SELECT DISTINCT SPJX.Si
FROM SPJ AS SPJX, SPJ AS SPJY, SPJ AS SPJZ WHERE SPJX.Pi = SPJY.Pi AND SPJY.Si = SPJZ.Si AND { SELECT P.COLOR
FROM P
WHERE P.Pi = SPJZ.Pi ) = 'Red' ;
7.15.36.SELECT S.St FROM S
WHERE S.STATUS < { SELECT S.STATUS
FROM S
WHERE S.Si = 'SI' ) ;
7.15.37.SELECT J.Ji FROM J
WHERE J.CITY = { SELECT MIN ( J.CITY )
FROM J ) ;
7.15.38.SELECT DISTINCT SPJX.Ji FROM SPJ AS SPJX WHERE SPJX.Pi = 'PI' AND ( SELECT AVG ( SPJY.QTY )
FROM SPJ AS SPJY WHERE SPJY.Ji = SPJX.Ji AND SPJY.Pi = 'PI' ) > ( SELECT MAX ( SPJZ.QTY ) FROM SPJ AS SPJZ WHERE SPJZ.Ji = 'Jl' ) ;
7.15.39.SELECT DISTINCT SPJX.Si FROM SPJ AS SPJX WHERE SPJX.Pt = 'PI'
AND SPJX.QTY > ( SELECT AVG ( SPJY.QTY )
FROM SPJ AS SPJY
WHERE SPJY.Pi = 'PI'
AND SPJY.Ji = SPJX.Ji ) ;
7.15.40. SELECT FROM WHERE
J.Ji J
NOT EXISTS
( SELECT *
FROM SPJ, P, S
WHERE SPJ.Jt = J.Jt
AND SPJ.Pf = P.Pt
AND SPJ.St = S.Sf
AND P.COLOR = 'Red'
AND S.CITY = 'London' ) ;
7.15.41.SELECT J.Jt FROM J
WHERE NOT EXISTS { SELECT * FROM SPJ
WHERE SPJ.Jt = J.Jt
AND NOT ( SPJ.St = 'SI' ) ) ;
7.15.42.SELECT P.Pt FROM P
WHERE NOT EXISTS ( SELECT * FROM J
WHERE J.CITY = 'London'
AND NOT EXISTS ( SELECT * FROM SPJ WHERE SPJ.Pf = P.Pt AND SPJ.Jt = J.Jt ) ) ;
7.15.43.SELECT S.Sf FROM S WHERE EXISTS ( SELECT * FROM P
WHERE NOT EXISTS ( SELECT * FROM J
WHERE NOT EXISTS ( SELECT * FROM SPJ WHERE SPJ.St = S.St AND SPJ.Pf = P.Pt AND SPJ.Jt = J.Jt ) ) ) ;
7.15.44.SELECT J.Jt FROM J
WHERE NOT EXISTS ( SELECT * FROM SPJ AS SPJX WHERE SPJX.St = 'SI' AND NOT EXISTS
( SELECT *
FROM SPJ AS SPJY
WHERE SPJY.PI = SPJX.PI
AND SPJY.Ji = J.JI ) ) ;
7.15.45.SELECT S.CITY FROM S UNION
SELECT P.CITY FROM P UNION
SELECT J.CITY FROM J ;
7.15.46.SELECT DISTINCT SPJ.Pi FROM SPJ
WHERE ( SELECT S.CITY FROM S
WHERE S.SI = SPJ.Si ) = 'London' OR ( SELECT J.CITY FROM J
WHERE J.Ji = SPJ.Ji ) = 'London' ;
7.15.47.SELECT S.SI, P.Pi
FROM S CROSS JOIN P EXCEPT
SELECT SPJ.Si, SPJ.PI
FROM SPJ ;
7.15.48. Решение опущено.
7.15.49-7.15.50. Решений не существует.
Глава
Целостность данных
8.1. Введение
Термин целостность данных используется для описания точности и корректности хранящейся в базе информации. Как отмечалось в главе 3, в базе данных может существовать любое количество ограничений целостности и в общем случае они могут быть произвольной сложности. Например, для базы данных поставщиков и деталей можно предположить, что номера поставщиков должны представляться в виде 'Snnnn' (где пппп — десятичное число, не превышающее 9999) и иметь уникальные значения; значения статуса поставщика должны находиться в диапазоне от 1 до 100, причем поставщики из Лондона должны иметь статус 20; количество поставляемых деталей должно быть кратно 50, причем красные детали должны храниться только в Лондоне; и т.д. В общем случае можно сделать заключение, что СУБД должно быть известно о подобных ограничениях и, безусловно, необходимо, чтобы СУБД тем или иным образом обеспечивала их выполнение (в основном, посредством отмены любых обновлений, нарушающих эти требования). Рассмотрим следующий пример (снова воспользуемся языком Tutorial D).
CONSTRAINT SC3
IS_EMPTY ( S WHERE STATUS < 1 OR STATUS > 100 ) ;
Смысл этого выражения таков: "Значения статуса поставщика должны находиться в диапазоне от 1 до 100". Обратите внимание на имя ограничения— SC3 (т.е. "Ограничение № 3 для поставщиков"). Под этим именем данное ограничение будет зарегистрировано в системном каталоге и именно это имя будет указываться в диагностических сообщениях системы при обнаружении попыток нарушения данного ограничения. Само ограничение задается в виде логического выражения, результат вычисления которого не должен иметь значение ложь (false).
Замечание. Для определенности здесь мы используем алгебраическую версию языка Tutorial D, поэтому логическое выражение часто будет принимать форму IS_EMPTY(...), которая означает, что в базе данных нет данных, нарушающих указанное ограничение (см. раздел 6.9 главы 6). Аналог приведенного выше примера в виде выражения реляционного исчисления может выглядеть следующим образом1.
CONSTRAINT SC3
' На практике бытует мнение, что ограничения (особенно сложные) легче формулировать в терминах реляционного исчисления, а не посредством выражений реляционной алгебры. В этой главе мы остановимся на алгебраических выражениях в соответствии с принципами изложения материала в остальной части книги, но читателю, несомненно, будет полезно поупражняться в преобразовании некоторых из приводимых ниже примеров в выражения реляционного исчисления.
FORALL SX ( SX.STATUS > 1 AND SX.STATUS < 100 ) ;
Здесь SX — переменная кортежа, которая изменяется на отношении поставщиков S.
По ходу отметим, что логическое выражение в ограничениях, представленных в виде выражений реляционного исчисления, должно быть закрытой формулой WFF (см. раздел 7.2 главы 7) и чаще всего будет иметь форму FORALL х(...}. Следовательно, выражение в данном примере означает, что все значения статуса поставщиков должны находиться в указанном диапазоне. На практике, конечно, достаточно, чтобы система просто проверяла лишь вновь вводимые или обновляемые значения статуса поставщиков, а не все те значения, которые уже хранятся в базе данных.
После того как новое ограничение будет объявлено, необходимо, чтобы оно было проверено системой, т.е. нужно убедиться, что база данных в текущий момент удовлетворяет вновь установленному ограничению. Если это не так, новое ограничение отвергается; в противном случае оно принимается (т.е. сохраняется в каталоге) и с этого момента вступает в силу. Объявление в системе приведенного выше ограничения приведет к тому, что СУБД будет контролировать все операции, которые подразумевают вставку кортежа для нового поставщика или изменение статуса существующего поставщика.
Конечно, дополнительно требуется, чтобы существовала возможность отмены установленного ранее ограничения.
DROP CONSTRAINT <имя ограничение ;
Например:
DROP CONSTRAINT SC3 ;
Замечание. Как вы, наверное, уже заметили, наше обсуждение сосредоточено на декларативной поддержке ограничений целостности. К сожалению, на сегодняшний день лишь немногие продукты предоставляют что-либо существенное в плане реализации такой поддержки, хотя ситуация в этом направлении пусть медленно, но все же улучшается. В некоторых продуктах (особенно в нереляционных) практикуется совсем другой подход, т.е. применяется процедурная поддержка ограничений целостности, построенная на использовании хранимых, или триггерных, процедур2. Однако можно предположить, что если бы существующие СУБД действительно предоставляли необходимую декларативную поддержку, то по крайней мере 90% текста определений типичной базы данных составляли бы объявления ограничений целостности данных. Таким образом, предоставляющая подобную поддержку система значительно облегчила бы труд прикладных программистов и позволила бы существенно повысить производительность их труда. Декларативная поддержка ограничений целостности является очень важным аспектом СУБД.
Хранимые,
или триггерные, процедуры — это заранее
скомпилированные процедуры, которые
могут вызываться из прикладных программ.
В качестве примера можно упомянуть
определенные пользователем операторы
ABS,
DIST, REFLECT и
т.д., которые рассматривались в разделе
5.2 (подраздел "Объявление оператора").
Такие процедуры логически можно
рассматривать как расширение СУБД (в
системах клиент/сервер они чаще всего
хранятся и выполняются на сервере). Мы
еще поговорим об этих процедурах в
разделе 8.8, в аннотациях к некоторым
публикациям в конце данной главы, а
также в главе 20.
точнее будет сказать, эволюционирует). Как отмечалось в главе 3, изначально акцент делался на первичных и внешних ключах (для краткости — просто на "ключах"). Однако со временем особое — даже ключевое! — значение ограничений целостности в общей картине осознавалось во все большей степени и оценивалось все выше. Одновременно начали возникать некоторые щекотливые вопросы, в частности относительно ключей. Структура этой главы отражает такое смещение акцентов, поскольку в начале (и еще в нескольких разделах) рассматривается общая проблема ограничений целостности, а затем — ключи, которые по-прежнему имеют большое практическое значение.
Схема классификации ограничений
В [3.3] ограничения целостности классифицируются по четырем основным категориям: ограничения типа (домена), атрибута, переменной-отношения и базы данных.
В ограничениях типа задаются допустимые значения для данного типа.
Замечание. В этой главе под типом подразумевается скалярный тип. Типы отношений, конечно, также являются объектами ограничений типов, но они представляют собой, по существу, просто логическое следствие ограничений типа, которые применяются к скалярным типам и в терминах которых эти типы отношений в конечном счете определены.
В ограничениях целостности атрибута задаются допустимые значения для данного атрибута.
В ограничениях целостности переменной-отношения задаются допустимые значения для данной переменной-отношения.
В ограничениях целостности базы данных задаются допустимые значения для этой базы данных.
Подробнее указанные виды ограничений рассматриваются в разделах 8.2-8.5 соответственно.