    Глава 19 

    Домены, отношения и типы данных 

    19.1. Введение 

    В главе 4 уже упоминалось, что домен в общих чертах представляет собой, 
возможно примитивный, встроенный системный тип данных, такой как INTEGER, 
FLOAT или BOOLEAN. В общем смысле домен — это определяемый пользователем тип 
данных, например supplier number (номер поставщика), part number (номер 
детали), weight (вес) или color (цвет). Каждый домен обладает концептуальным 
набором скалярных значений (или скаляров), из которого различные атрибуты 
разных отношений получают свои реальные значения. Говорят, что такие атрибуты 
определены на рассматриваемом домене. Каждый атрибут можно определить только 
на одном домене. 
    Прежде чем продолжить дальнейшее обсуждение, необходимо заметить, что 
пользователь, определяющий новый домен, — это не рядовой пользователь базы 
данных. Задача определения нового домена требует, как минимум, специальных 
знаний в сфере информационных технологий (ИТ), так как подразумевает 
определение операторов, применимых к элементам нового типа. Поэтому такой 
пользователь обычно является профессионалом в области ИТ, возможно, одним из 
администраторов базы данных. (Иногда таких пользователей называют 
"настройщиками базы данных".) 
    Между прочим, следует напомнить и о термине "абстрактный тип данных", или 
АТ'Д, который иногда используется наравне с термином "тип данных, определяемый пользователем". 
    Как уже отмечалось ранее, для операций сравнения требуется, чтобы операнды 
были определены на одном и том же домене, т.е. домены ограничивают операции 
сравнения. В главе 6 было показано, что домены также ограничивают некоторые 
операции реляционной алгебры, а именно те, в которых либо явно (как в операции 
выборки), либо неявно (как в операции деления) выполняются скалярные операции 
сравнения, В частности, операции объединения, пересечения и вычитания требуют, 
чтобы операнды были совместимы по типу. Совместимость типов определим 
следующим образом. Говорят, что два отношения базы данных совместимы по типу, 
если они обладают идентичными заголовками, т.е. отношения обладают идентичными 
наборами имен атрибутов и атрибуты с одинаковыми именами определены на 
одинаковых доменах, (Более точно это определение сформулировано ниже в этой главе.) 
    В ходе изложения уже отмечалось, что в данной концепции заложено 
значительно больше, чем может показаться на первый взгляд. Ранее мы обещали 
вернуться к обсуждению доменов и типов данных в последующих главах. И теперь 
приводим обещанный материал. 

    19.2. Домены 

    Начнем обсуждение доменов. Прежде всего рассмотрим эффект доменов на 
скалярных операциях сравнения, таких как =, ^, < и т.п. 

    518	Часть V, Дополнительные аспекты 

    Отмена проверки доменов 

    Уже было отмечено, что домены ограничивают операции сравнения. Например, в 
контексте базы данных поставщиков и деталей операция сравнения SP.S# = s.st 
вполне корректна, так как ее операнды определены на одном домене. В то же 
время операция SP.P# = s.s# абсолютно некорректна, так как ее операнды 
определены на разных доменах. Однако в [4.4] Кодд предлагает версии некоторых 
(но не всех) операций реляционной алгебры с отменой проверки доменов 
(ОПД-операции), что позволяет выполнять рассматриваемые операции, даже если их 
операнды определены на различных доменах. Возможность отмены проверки доменов, 
например для операции соединения, позволит выполнить соединение, даже если 
соединяемые атрибуты определены на различных доменах. 
    Оправданием ОПД-операций может служить то, что существует возможность 
возникновения ситуаций, когда пользователь знает больше, чем система. 
Например, в базе данных, которая содержит информацию о поставщиках и 
покупателях, запрос "Получить поставщиков, являющихся одновременно 
покупателями" может потребовать выполнения сравнений номеров поставщиков и 
номеров покупателей, которые определены на двух различных доменах. И если этот 
запрос действительно создан пользователем, то система не должна препятствовать 
выполнению такого запроса. Следовательно, в некоторых случаях возникает 
необходимость в отмене проверки принадлежности значений определенному домену. 
С точки зрения автора этой книги, ОПД-операции — далеко не лучший способ 
удовлетворения этого требования. 
    Прежде всего, корректности даже такого простого выражения, как p.WEIGHT > 
15, достаточно, чтобы показать, что в некотором смысле "междоменные" сравнения 
необходимы. Кроме всего прочего, в данном примере вес (WEIGHT) сравнивается с 
целым числом, a WEIGHT (вес) и INTEGER (целое число) являются 
(предположительно) разными доменами. Но, кроме приведенного аргумента, 
существует еще несколько. Давайте перейдем к примеру посложнее. Рассмотрим 
сравнение веса детали и количества деталей в партии. 

    P.WEIGHT > SP.QTY 

    Предположим, что WEIGHT и QUANTITIES (количество) — это разные домены. 
Можно согласиться, что показанное сравнение не имеет смысла, т.е. это 
выражение некорректно. Но предположим, что выражение записано несколько иначе: 

    P.WEIGHT - SP.QTY > 0 

    Согласно [4.4] такое сравнение нужно рассматривать как корректное. В 
данном случае система не выполняет проверки доменов, подобно выполненной в 
предыдущем сравнении, а только подтверждает, что все рассматриваемые значения 
принадлежат одному "базовому типу данных" (в этом примере все величины 
являются числами). Другими словами, два выражения, которые абсолютно идентичны 
с логической точки зрения, явно имеют различающуюся семантику. Но такое 
положение вещей неприемлемо. Следовательно, как описано в [4.4], в базовом 
понятии домена существует нечто подозрительное, а значит, какая-то неясность 
закралась и в понятие "отмена проверки доменов". 
    Далее рассмотрим следующие сравнения: 

    S.S# = 'ХЗ1 Р.Р# = 'РЗ' S.S# = Р.Р# 

    Из трех приведенных выражений 
    •   первое корректно и может иметь значение истина', 
    •   второе корректно и может иметь значение истина', 
    •   третье некорректно. 

    Глава 19. Домены, отношения и типы данных	519 

    Другими словами, может быть три значения, пусть это а, Ь и с, таких, что а 
= с истинно (т.е. имеет значение истина) и b = с также истинно, но а = b не 
будет иметь значение истина, так как нельзя даже записать такое выражение! Как 
можно объяснить подобную ситуацию? 
    Дело в том, что в корректных выражениях используются неявные 
преобразования типов. В первом сравнении литерал "ХЗ" неявно преобразуется к 
типу S#; таким образом, в сравнении участвует два номера поставщиков, что 
вполне корректно. Во втором сравнении "ХЗ" неявно преобразуется к типу Р#, а 
значит, в сравнении участвует два номера деталей, что также вполне корректно. 
Но в третьем сравнении не существует известного системе преобразования, с 
помощью которого можно преобразовать номер поставщика в номер детали и 
обратно. Поэтому третье сравнение завершается неудачей с генерацией ошибки 
несовместимости типов. 
    (Конечно, при рассуждениях о неявном преобразовании типов важно понимать, 
что само преобразование иногда может завершаться неудачей. В частности, так 
будет, если значение, которое нужно преобразовать, не имеет соответствующего 
значения в целевом домене; например, при преобразовании строки "Red" 
("красный") к типу номера поставщика S#.) 
    Таким образом (повторимся), S# и Р# являются определяемыми пользователем 
типами данных, каждый из которых определен в терминах базового системного типа 
данных "символьная строка". Не вызывает сомнений, что процесс определения 
домена включает определение функций приведения типов, например для 
преобразования символьной строки в номер поставщика или в номер детали. Эти 
функции неявно используются системой при работе с выражениями, подобными двум 
корректным сравнениям, приведенным выше. Кроме того, пользователь, 
определяющий домен, должен определить функцию (пусть это будет функция CHAR) 
для "обратного преобразования", т.е. для преобразования номера поставщика или 
детали в символьную строку. И если необходимо сравнить номер поставщика и 
номер детали, то на самом деле надо сравнивать их строковые представления: 

    CHAR   (  S.S#   )   = CHAR   (  Р.Р#   ) 

    Такие механизмы, использующие функции явного или неявного приведения 
типов, обеспечивают "отмену проверки доменов", но делают это вполне понятным и 
систематическим (а не специальным) способом. В частности, нет необходимости 
загромождать реляционную алгебру новыми операциями, такими как ОПД-соединение 
и т.п. 
    Подытожим. Вместо утверждения, что операнды каждого оператора сравнения 
должны быть определены на одном домене, лучше и точнее требовать, чтобы 
операнды были совместимыми по типу. Таким образом, для данной операции 
сравнения А 6 В (где А и В — скалярные величины, а 0 — оператор сравнения) 
должно выполняться одно из следующих утверждений: а)АнВ принадлежат к одному 
типу (т.е. определены на одном и том же домене); б) должны существовать такие 
известные системе функции приведения типов, чтобы А и В можно было привести к 
одному типу (т.е. к одному домену). 
    Приведенные рассуждения в сфере программирования известны под названием 
строгая типизация. Разные авторы приводят несколько различающиеся определения 
этого понятия. Тем не менее, в том смысле, который придает этому понятию автор 
данной книги, строгая типизация означает, кроме всего прочего, следующее: а) 
все имеет свой тип; б) для каждого выражения система проверяет два условия: 
либо операнды каждого оператора принадлежат к типу, который приемлем для 
данного оператора, либо существуют соответствующие функции приведения типов 
операндов к приемлемому для данного оператора типу. (Здесь следует отдельно 
отметить, что в изложенном утверждении "выражение" означает не только 
выражение сравнения.) Строгая типизация — это хорошая идея, так как она 
обеспечивает основу для выявления ошибок несовместимости типов на этапе 
компиляции, а не во время выполнения. 

    520	Часть V. Дополнительные аспекты 

    И еще одно замечание. Некоторые авторы выступают за исключительно жесткую 
форму строгой типизации, согласно которой приведение типов всегда должно 
выполняться явно, а неявно — никогда. В подобных схемах даже такое простое 
сравнение, как P.WEIGHT > 15, будет синтаксически некорректным 
(предполагается, что домен WEIGHT не совпадает с доменом INTEGER), и данное 
выражение нужно будет записывать, например, так: p.WEIGHT > WEIGHT(15). Но, 
исходя из целей данной главы, будем дальше предполагать, что приведение типов 
может выполняться неявно. 

    Другие скалярные операции 

    Рассматриваемая нами концепция является концепцией строгой типизации; 
признание этого факта говорит о том, что данная концепция применима не только 
к операциям сравнения (несмотря на то что в большей части работ по базам 
данных она обсуждается именно относительно операций сравнения). Например, 
рассмотрим следующие выражения: 

    P.WEIGHT + SP.QTY P.WEIGHT * SP.QTY 

    Первое из них предположительно не имеет смысла, поэтому база данных должна 
отбросить его. Но второе выражение имеет определенный смысл: оно представляет 
общий вес всех деталей, включенных в одну партию (поэтому результат также 
определен на домене WEIGHT, т.е. принадлежит к типу WEIGHT). 
    Таким образом, полная поддержка понятия домена должна включать, по крайней 
мере, перечисленные ниже возможности. 
    1.  Для каждого домена Di возможность указания корректных унарных 
операторов, которые можно применять к значениям di из этого домена. Это даст 
системе информацию о том, что символьная строка, кроме всего прочего, может 
быть преобразована в номер поставщика и (по принципу исключения) что номер 
поставщика не может быть преобразован в номер детали. 
    2.  Для каждой пары доменов Di и Dj (не обязательно различных) возможность 
указания корректных бинарных операторов, которые можно применять к парам 
значений di и dj из этих доменов. Это даст системе информацию, например, о 
том, что выражения SP.S# = s.s# и p.WEIGHT * SP.QTY корректны и (по принципу 
исключения) что выражения SP.P* = s.s# и p.WEIGHT + SP.QTY некорректны. В 
частности, заметьте, что таким образом система получает информацию о том, 
какой из операторов сравнения применим к рассматриваемым доменам. Например, к 
значениям из домена SEX (пол), который содержит значения "Мужчина" и 
"Женщина", применимы только операторы "=" и "*", а оператор "<" не имеет смысла. 
    3.  В более общем смысле возможность указания для каждой комбинации из п 
не обязательно различающихся доменов (и > 0) корректного и-арного оператора, 
который можно применять к наборам из п значений, по одному из каждого 
соответствующего домена. 
    4.  Для каждого корректного оператора возможность указания домена 
результата этого оператора. Это предоставит системе информацию, например, о 
том, что результатом умножения веса детали на количество деталей в партии 
будет значение из домена веса. 

    Изложенные требования имеют ряд важных следствий. 

    •   Первое и самое важное: из указанных требований следует, что системе 
известно, какое именно выражение является корректным, а также известен домен 
результата каждого корректного выражения. 
    •  Из перечисленных требований также следует, что множество всех доменов 
должно быть замкнутым (для конкретной базы данных или другой операционной

    Глава 19. Домены, отношения и типы данных	521 

единицы "большого объема информации"). Другими словами, домен результата 
произвольного корректного скалярного выражения должен быть известен системе. В 
частности, заметьте, что замкнутое множество доменов должно содержать домен 
"Boolean" (т.е. домен истинностных значений), если принято считать сравнения 
корректными выражениями! 
    •  И наконец, поскольку системе известен домен результата каждого 
корректного выражения, следовательно ей также известно, какие скалярные 
присвоения являются корректными. Заметьте, что система нуждается в этой 
информации для корректной обработки операций INSERT и UPDATE, так как обе эти 
операции неявно используют скалярные присвоения, 

    Скалярные значения 

    До сих пор ничего не было сказано о природе значений, которые могут 
появляться внутри домена, за исключением того, что эти значения были названы 
скалярными значениями, или скалярами. В примерах автор стремился показать, что 
скаляры — это очень простые значения (символьной строки, числа и т.д.). Но 
важно понимать, что в реляционной модели не существует ничего, что требует 
ограничить скалярные значения такими простыми формами. Фактически эти 
"скалярные" значения могут быть настолько сложными, насколько мы пожелаем. 
Поэтому можно определить домены инженерных чертежей, юридических контрактов, 
геометрических рисунков и т.д. Единственное требование к скалярным значениям 
состоит в том, что любая внутренняя структура, которой могут обладать скаляры, 
должна быть невидимой для СУБД. Другими словами "с точки зрения" СУБД эти 
значения должны быть действительно скалярными (или "атомарными"). Используя 
жаргон, можно сказать, что эти значения должны быть инкапсулированными. 
Говорят, что если система поддерживает атомарность значений в описанном выше 
смысле, то система удовлетворяет требованиям инкапсуляции, 
    Может показаться, что в данном обсуждении термин "скаляр" не очень 
уместен. Но это не так. Несмотря ни на что атомы в физике соответствуют 
понятию "атомарный" (т.е. неделимый), только если рассматривать их с 
определенной точки зрения. На самом деле атомы обладают внутренней структурой, 
но эту внутреннюю структуру при работе на определенном уровне абстракции 
полезно и удобно игнорировать. Поэтому в данной книге и далее будет 
употребляться термин "скаляр", даже если придется признать, что на низком 
уровне абстракции эти скаляры могут обладать структурой произвольной 
сложности. (Скаляры даже могут быть отношениями!) 
    Пришло время привести пример. Предположим, имеется база данных плоских 
фигур (кругов, прямоугольников, многоугольников и т.п.). В этой базе данных 
очень полезно определить домен точек POINT. Ниже показан один из способов 
определения такого домена. 

    CREATE DOMAIN POINT REP   ( X FLOAT,   Y ПЛАТ  )   ; 

    Здесь REP — это сокращение от representation (представление). С помощью 
этого оператора определяется внутренняя структура значений домена. Таким 
образом, значения домена POINT состоят из двух значений X и Y типа FLOAT, 
соответствующих координатам хну рассматриваемой точки в декартовой системе 
координат. С другой стороны, точки можно представлять в терминах полярной 
системы координат: 

    CREATE DOMAIN РОЮТ REP   (  R ЕЪОАТ,   THETA FLOAT  )   ; 

    Для простоты предположим, что в дальнейшем изложении будет использоваться 
декартова система координат. Но в любом случае выбор системы координат не 
имеет значения, так как внутреннее представление будет скрыто от пользователя 
(см. обсуждение функций ниже). 

    522	Часть V, Дополнительные аспекты 

    Теперь можно определить отношения, в которых используется домен POINT. Например: 

    CREATE BASE RELATION TRIANGLES ( TRIANGLE_ID . . ., A DOMAIN ( POINT ), В 
DOMAIN ( POINT ), С DOMAIN ( POINT ) ) CANDIDATE FEY ( TRIANGLE_ID ) CANDIDATE 
KEY ( А, В, С ) ; 

    Заметьте, что данное отношение имеет четыре атрибута, а не семь. Тот факт, 
что значения трех атрибутов внутренне представлены парами значений типа FLOAT, 
не играет роли, с точки зрения пользователя (а также СУБД). 
    Как показано выше, необходимо также определить операции или функции (эти 
термины будут использоваться как синонимы), которые можно применять к данным 
типа POINT. В частности, необходима функция, которую можно назвать также 
POINT, создающая значение типа POINT по указанным значениям координат х и у. 
Ниже показан код этой функции. 

    CREATE FUNCTION POINT ( A FLOAT, В FLOAT ) RETURNS { POINT ) AS BEGIN ; 
    DECLARE P POINT ; P.X := A ; P.Y := В ; RETURN ( P ) ; END ; 

    Функция POINT преобразует пару значений типа FLOAT в точку (это пример 
функции, которую иногда называют функцией-конструктором). Выражения р.х и P.Y 
ссылаются соответственно на компоненты X и Y внутреннего представления точки р. 
    Какие еще функции нужны для работы с данными типа POINT? Ниже приведены 
еще два явных претендента. 

    CREATE FUNCTION X ( P POINT ) RETURNS ( FLOAT ) AS BEGIN ; 
    RETURN ( P.X ) ; END ; 
    CREATE FUNCTION Y ( P POINT ) RETURNS ( FLOAT ) AS BEGIN ; 
    RETURN ( P.Y ) ; END ; 

    Функции х и Y возвращают соответственно х- и у-координату аргумента POINT. 
Обратите внимание! Такие функции могут понадобиться, даже если в качестве 
внутреннего представления выбрана полярная, а не декартова, система координат. 
Более того, могут понадобиться функции R и ТНЕТА, возвращающие полярные 
координаты аргумента. Названные функции определяются аналогично функциям х и 
Y, за исключением различий во внутреннем представлении. 
    Ниже показан пример использования функций х и Y. 

    Р  := POINT   ( X(P),   -Y(P)   )   ; 

    Здесь Р — переменная типа POINT, представляющая, например, точку р. В 
результате выполнения приведенного выражения переменная Р будет представлять 
точку р', которая симметрична точке р относительно оси х. Другими словами, 
если переменная Р представляла точку с координатами (х, у), то после 
выполнения приведенного выражения в переменной Р будут храниться координаты 
(х, -у). 
    Заметьте, что функции, такие как POINT, х, Y (и т.д.), являются основой 
единственного способа, с помощью которого пользователи могут оперировать 
данными типа POINT. В частности, заметьте, что внутреннее представление точки 
как двух чисел типа FLOAT "видимо" для подобных функций и "не видимо" для 
пользователей этих функций, а также для СУБД. Это понятие можно описать 
другими словами — подобным функциям позволено разрушать инкапсуляцию, а 
пользователям — нет. 

    Глава 19. Домены, отношения и типы данных	523 

    Кстати, необходимость определения функций для работы с данными в 
рассматриваемом домене вовсе не означает, что определения этих функций должны 
быть связаны с определением рассматриваемого домена, И хотя подобное 
связывание можно аргументировать для функций, которые работают с данными 
одного домена, оно не применимо к функциями, работающим с данными нескольких 
доменов. Например, ранее мы говорили, что должны предоставить пользователям 
возможность умножать вес детали на количество деталей в партии. Однако должно 
ли определение функции произведения веса детали на их количество быть связано 
с определением домена WEIGHT или домена QTY? Наилучший ответ: "Определение 
данной функции не должно быть связано ни с одним из определений этих доменов" . 
    Вернемся к примеру домена POINT. Другим полезным доменом для базы данных 
по геометрии является домен LINESEG (от англ, line segment — отрезок прямой), 
определение которого приведено ниже. 

    CREATE DOMAIN LINESEG REP ( START POINT, END POINT ) ; 

    Иными словами, внутренняя структура данного домена описана в терминах 
ранее определенных пользователем доменов, а не только системных доменов, как 
это делалось во всех предыдущих примерах. 
    Это обсуждение нельзя завершать без нескольких ссылок на последующий 
материал и определения некоторых терминов. 
    Во-первых, было показано, что домены являются типами данных, возможно 
определяемыми пользователем, в общем произвольной внутренней сложности. При 
беглом взгляде на объектно-ориентированные базы данных можно заметить, что 
одной из основных объектно-ориентированных концепций является концепция класса 
объектов. Этот класс представляет собой тип данных, возможно определяемый 
пользователем, в общем произвольной внутренней сложности. Другими словами, 
домены и классы объектов обозначают одно и то же. Следовательно, нами получен 
способ объединения двух технологий (реляционной и объектно-ориентированной). 
Этот вопрос будет подробнее обсуждаться далее в книге. 
    Во-вторых, если значения домена могут иметь произвольную внутреннюю 
сложность, то из этого следует, что данный домен (а значит, и атрибуты, 
определенные на этом домене) может содержать в некоторых случаях значения, 
которые являются отношениями. Иначе говоря, должен существовать способ 
определения отношений, которые в качестве значений содержат другие отношения 
(несмотря на требования по нормализации). Этот вопрос более глубоко 
обсуждается несколько ниже. 
    В-третьих, терминология. В предыдущих изданиях этой книги разделялись 
понятия простого и составного доменов. "Простыми" называли домены, состоящие 
только из простых значений (например, числа, строки и т.д.). "Составными" 
называли домены, которые в основном являлись комбинацией простых доменов. 
Например, рассмотрим три простых домена: YEAR (год), MONTH (месяц) и DAY 
(день), тогда составной домен DATE (дата) можно определить достаточно явным 
способом. Тем не менее, из всего изложенного должно быть понятно, что подобная 
возможность не очень нужна — она полностью реализуется с помощью механизма 
определяемых пользователем типов данных, о котором упоминалось выше. Таким 
образом, далее мы не будем соглашаться с выдвинутым в [4.4] требованием, чтобы 
поддержка составных доменов в изложенном выше смысле явно присутствовала в 
реляционной модели. 

    Инструкции CREATE и DESTROY DOMAIN 

    Посвященный доменам раздел завершается коротким обсуждением синтаксиса и 
семантики ИНСТРУКЦИЙ CREATE  DCMAIN И DESTROY DOMAIN. Сначала рассмотрим ИНСТРУКЦИЮ 

    CREATE DCMAIN. 
    CREATE DCMAIN domain representation  [   conditional-expression ] 

    524	Часть V. Дополнительные аспекты 

    Здесь domain—ЭТО ИМЯ ДОМСНЗ, НСОбяЗЗТСЛЬНЫЙ Параметр 
conditional-expression — это ограничение целостности (см. главу 16), a 
representation принимает следующую форму: 

    REP  (  component-rep-conmalist ) 

    В свою очередь, component-rep-commaiist— это список элементов через 
запятую; каждый элемент списка состоит из необязательного имени компонента, 
после которого следует тип указанного компонента (см. примеры, приведенные 
выше в этой главе). 
    Замечание. Если список состоит только из одного элемента списка и имя 
компонента опущено, то ключевое слово КЕР и скобки можно также не 
использовать, а инструкция CREATE DOMAIN будет сведена к форме, которая 
использовалась во всех примерах, приведенных в предыдущих глзвах. 
    Что касзется инструкции DESTROY DOMAIN, то ее синтаксис был показэн в 
главе 4. 

    DESTROY DOMAIN domain ; 

    В глзве 4 тзкже отмечалось, что эта операция завершится неудачей, если 
хотя бы одно отношение содержит атрибут, который определен на удаляемом 
домене. Кроме того, эта операция завершится неудачей, если любые другие домены 
используют в определениях значения удаляемого домена, результат любой 
корректной скалярной оперзции определен нз удаляемом домене или любой другой 
домен определен как подтип рассматривземого доменз. 

    19.3. Отношения 

    Теперь сосредоточимся на отношениях. Как и при обсуждении доменов выше в 
этой главе, начнем с рассмотрения операций сравнения; в дзнном случзе, 
конечно, с реляционных оперзции сравнения (см. глзву 6). 

    Реляционные операции сравнения 

    Выше было отмечено, что домены являются скалярными типами данных (с 
оговоркой, что рассматриваемые скаляры нз сзмом деле могут иметь произвольную 
сложность, но на определенном уровне абстракции любая подобная внутренняя 
структура скрытз от пользователя и от СУБД). Современные языки 
программирования позволяют определять некоторые составные типы данных; их 
можно строить нз других типзх дзнных (которые, в свою очередь, могут быть 
скзлярными или составными) с помощью конструкторов типов. Например, массивы и 
списки являются конструкторами типов, следовательно, можно построить составной 
тип дзнных, который предстзвляет собой массив целых чисел, список массивов 
целых чисел, массив списков массивов символьных строк и т.п. 
    Подобно этому, отношения являются конструкторами типов в реляционной 
модели. Если создается отношение (либо бззовое, либо порожденное), то, кроме 
всего прочего, определяется состзвной тип дзнных "множество кортежей", в 
котором кортежи также принадлежзт к составному типу, а именно к типу, 
определенному заголовком нового отношения. Поскольку при сравнении двух 
скаляров они должны быть совместимы по типу, то и при сравнении двух отношений 
они тзкже должны быть совместимы по типу. Совместимость отношений по типу 
более точно можно определить тзк. Двз отношения являются совместимыми по типу 
тогдз и только тогдз, когдз 
    1) обз отношения имеют один и тот же набор имен атрибутов (заметьте, что и 
после выполнения оперзции сравнения это условие должно соблюдаться); 
    2) соответствующие атрибуты (т.е. атрибуты с идентичными именами в двух 
отношениях) совместимы (в смысле, изложенном выше в этой главе). 

    Глава 19. Домены, отношения и типы данных 525 


    Другие реляционные операции 

    Не требует дополнительного объяснения тот факт, что понятие совместимости 
по типам распространяется не только на реляционные операции сравнения. Если 
быть точным, это понятие распространяется на реляционные присвоения (например, 
если отношение В присваивается отношению А, то А и В должны быть совместимы по 
типу). Кроме того, понятие совместимости по типу распространяется на операции 
реляционной алгебры объединение, пересечение и вычитание. В связи с этими 
возникает вопрос о типе (или заголовке) результата произвольного реляционного 
выражения (т.е. порожденного отношения). Именно этот вопрос и рассматривается ниже. 
    Нам известен набор правил, которые определяют имена атрибутов 
произвольного порожденного отношения (см. главу 6). Но заголовок отношения — 
это не только набор имен атрибутов, это набор пар (имя атрибута, имя домена). 
Это не принималось во внимание в главе 6, так как там предполагалось, что 
операнды должны быть определены на одном домене когда бы ни производилось 
скалярное сравнение. Но теперь мы пришли к выводу, что для сравнения 
достаточно, чтобы операнды были совместимы по типу и не обязательно определены 
на одном домене. Таким образом, можно попытаться соединить (выполнить операцию 
соединения) два отношения А{Х, Y} и B{Y, Z}, где общий атрибут У определен на 
домене YA в отношении А и на домене YB в отношении В. При условии, что домены 
YA и YB совместимы по типу, соединение будет вполне выполнимо, в результате 
чего будет получено отношение, например С, с атрибутами {X, Y, 7}. Но на каком 
домене определен атрибут Y в отношении С? Это должен быть либо домен YA, либо 
YB, но какой из ни х — неизвестно. 
    Из совместимости по типу доменов YA и YB следует, что либо значения типа 
YA можно преобразовать в соответствующие значения типа YB или наоборот, либо 
возможно преобразование в обоих направлениях. Неоднозначности возникают только 
в случае "обоих направлений". В этом случае в качестве домена результата можно 
выбрать тот домен (УА или YB), который имеет больший приоритет. (Понятие 
приоритета доменов можно не вводить, если не поддерживаются неявные 
преобразования типов. В результате можно избежать "несколько неожиданного 
следствия", описанного ниже.) Например, если YA является доменом номеров 
поставщиков и YB — доменом символьных строк, предпочтительнее, чтобы результат 
операции был определен на домене номеров поставщиков (YA), т.е. этот домен 
рассматривается как более приоритетный по сравнению с доменом символьных 
строк. Подобные правила приоритетов являются встроенными для системных типов 
данных, но в остальных случаях эти правила должен определять создатель домена. 
Выше в этой главе по умолчанию предполагалось, что такие правила существуют и 
система может неявно преобразовывать символьную строку в номер поставщика, но 
не наоборот. 
    Концепция совместимости и (во многих случаях) приоритетности типов 
применяется не только к операции соединения, но и к большинству других 
реляционных операций, включая, в частности, операции объединения, пересечения 
и вычитания. Так как детальное изложение достаточно утомительно, то его можно 
опустить. (Наверное, следует отметить одно несколько неожиданное следствие 
концепции приоритетности доменов, которое состоит в том, что, например, 
объединение может на вполне корректных основаниях включать кортежи, которые не 
присутствуют ни в одном из двух операндов!) 
    Между прочим, это позволяет понять, почему термин "совместимы по 
объединению" не совсем корректен. С одной стороны, эта концепция 
распространяется не только на операцию объединения, С другой стороны, 
непосредственно к объединению эта концепция не применима, ее можно применять 
только на специальной операции объединения, которая определена в реляционной 
алгебре. Кроме того, фраза "Отношения А и В совместимы для (реляционной) 
операции соединения тогда и только тогда, когда А и В являются совместимыми по 
соединению" воспринимается как 

    526	Часть V. Дополнительные аспекты 

тавтология. И последний аргумент. Различные СУБД, различные языки и 
различные исследователи предлагают разные определения данной концепции. 
Например, определение, изложенное в [4.4], является более узким, чем то, 
которое используется в данной главе. Именно по этим и многим другим причинам в 
данной книге часто используется термин "совместимы по типу". 

    Кортежи 

    Мы уже обсудили домены (являющиеся скалярными типами) и отношения (которые 
сами по себе типами не являются, а принадлежат к некоторому составному типу), 
но пропустили в обсуждении кортежи, которые также принадлежат к определенному 
(составному) типу (кортеж— это еще один конструктор типа). В основном кортеж — 
это множество упорядоченных пар 

    {   <Al:vl>,   <A2:v2>,   ...,   <An:vn> }, 

    в котором каждое Ai— это имя атрибута, а каждое v/— значение из 
(уникального) домена ?>/, соответствующего атрибуту Ai. (Заметьте, что — по 
крайней мере в реляционной алгебре, определение которой используется в этой 
книге, — кортежи могут появляться только в контексте, в котором 
соответствующие отношения всегда и хотя бы неявно известны и, следовательно, 
соответствующие каждому атрибуту домены также всегда известны.) Таким образом, 
каждый кортеж имеет свой тип, или заголовок 

    (   <A1:D1>,   <A2:D2>,   ...,   <An:Dn> }. 

    Следовательно, концепция типов и совместимости по типу распространяется и 
на кортежи. Не углубляясь в подробности, заметим, что эта концепция, конечно, 
распространяется на операции присвоения и сравнения кортежей. Присвоения 
кортежей выполняются (неявно) в процессе выполнения операций INSERT и UPDATE. 
Сравнения кортежей выполняются (опять же в основном неявно) в перечисленных 
ниже случаях (кроме прочих явных случаев). 
    •   Обработка операций объединения, пересечения и вычитания. 
    •   Обработка операций соединения и деления. 
    •   Обработка суммирующих итогов. 
    •   Проверка принадлежности кортежа отношению с помощью оператора 
принадлежности множеству е. 
    •   Проверка целостности на уровне ссылок. 

    19.4. Наследование типов 

    Основная идея наследования типов была представлена и кратко обсуждена в 
главе 12. Здесь эта идея, а также связанные с ней концепции подтипа и 
супертипа рассматриваются более детально. 
    Как уже отмечалось, существует немало разногласий в толковании этих 
терминов. Тем не менее, в общем смысле утверждают, что тип Y является подтипом 
типа X (и соответственно тип X является супертипом типа Y) тогда и только 
тогда, когда каждый экземпляр типа Y обязательно принадлежит к типу X. 
Например, тип CIRCLE (окружность) является подтипом типа ELLIPSE (эллипс). 
Аналогично, тип ELLIPSE является супертипом для типа CIRCLE, так как каждая 
отдельная окружность является частным случаем эллипса. Конечно, обратное 
утверждение неверно (т.е. отдельный эллипс не является частным случаем окружности). 
    В чем же полезность такой концепции? Одна из причин (опять же в общем 
смысле) такова: если системе известно, что каждый экземпляр типа К является 
экземпляром типа X, то ей также известно, что все свойства экземпляров типа X 
присущи экземплярам типа Y. В этом случае утверждают, что тип Унаследует 
свойства типа А'. 

    Глава 19. Домены, отношения и типы данных	527 

    Поэтому пользователь всегда может применять данные типа Y там, где 
разрешено использование данных типа X; этот принцип называют принципом 
подстановки. Например, функция, которая получает аргумент типа ELLIPSE, всегда 
может быть вызвана с аргументом типа CIRCLE. 
    Замечание. Подстановка не распространяется на функции, которые разрывают 
инкапсуляцию, так как супертип и подтип могут иметь разную внутреннюю структуру. 
    В литературе по этой теме часто встречается термин многократное 
использование. Многократное использование означает, что, например, код, 
выполняющий некоторые операции над данными типа X, может быть использован без 
изменений для выполнения аналогичных операций над данными типа Y. Например, 
код, который поворачивает эллипс на 90°, можно применить и к данным типа 
CIRCLE, хотя поворачивать окружность не имеет смысла. 
    Изложенные соображения можно применять на уровне доменов и на уровне 
отношений. Ниже рассматриваются оба случая.

    Домены 

    Предположим, что домен эллипсов ELLIPSE определен следующим образом: 

    CREATE DOMAIN ELLIPSE REP   ( A FLOAT,   В ПЛАТ  )   ; 

    Для простоты изложения допустим, что в рассмотрение входят только эллипсы, 
центр которых расположен в начале координат. Значения А и В — это длины 
полуосей рассматриваемого эллипса (уравнение эллипса выглядит так: —^ +—2=1). 
    Определим функцию, которая вычисляет площадь выбранного эллипса: 

    CREATE FUNCTION AREA ( Е ELLIPSE ) RETURNS ( FLOAT ) AS BEGIN ; 
    RETURN ( PI * E.A * E.B ) ; 
    END ; 

    Здесь PI — это математическая константа л (площадь эллипса составляет 
nab). Заметьте, что эта функция разрывает инкапсуляцию (так как ссылается на 
компоненты внутреннего представления). 
    Теперь определим домен окружностей CIRCLE, указав, что этот домен является 
подтипом домена эллипсов: 

    CREATE DOMAIN CIRCLE   (  R ПЛАТ  )   ISA   (   ELLIPSE  )   ; 

    В данном определении необходимо отметить следующее. 
    1.  Ключевое слово ISA (от англ, "is a" — является) используется, как 
показано в примере, для формирования связи подтип-супертип. 
    2.  Заметьте, что из утверждения "каждый экземпляр У является экземпляром 
X" не следует, что внутренняя структура значений типа Y должна совпадать с 
внутренней структурой значений типа X (внутренние структуры могут быть 
подобными, но не обязательно так и будет). В данном примере эллипсы 
представлены с помощью длин двух своих полуосей А и В, в то время как 
окружности представляют посредством радиуса R. Тем не менее, из утверждения 
"каждый экземпляр К является экземпляром X" следует, что любой экземпляр типа 
Y можно привести к типу А'. (Упражнение для читателя. Напишите функцию 
приведения значения типа CIRCLE к типу ELLIPSE.) 
    3. Окружности являются частным случаем эллипсов, поэтому функции, подобные 
AREA, должны быть применимы и к окружностям. Из-за указанных в пункте 2 
различий во внутреннем представлении необходимо переопределить функцию AREA 
следующим образом; 

    528	Часть V. Дополнительные аспекты 

    CREATE FUNCTION AREA AS BEGIN ; 
    С CIRCLE ) RETURNS ( FLOAT ) 
    RETURN ( PI * ( C.R 2 ) ) 
    END 

    Замечание. Конечно, площадь данной окружности нужно всегда вычислять путем 
приведения окружности к типу ELLIPSE и применения к результату функции AREA, 
которая определена для типа ELLIPSE. 

    4.  Так как окружность является частным случаем эллипса, то весьма 
вероятно, что существуют функции, которые применимы только к окружностям, а не 
ко всему множеству эллипсов. Например, функция определения диаметра: 

    CREATE FUNCTICN DIAMETER ( С CIRCLE ) RETURNS ( FLOAT ) AS BEGIN ; 
    RETURN ( 2 * C.R ) ; 
    END ; 

    Чтобы избежать неясностей, следует явно указать, что подтип (как показал 
пример) обладает супермножеством функций (т.е. более мощной функциональностью). 
    5.   Теперь заметьте, что если записать выражение 

    AREA  (  figure ), 

    где figure— это переменная, то на этапе компиляции система не сможет 
определить, является ли аргумент функции окружностью или это просто эллипс. 
Если это случилось (т.е. система не смогла определить тип аргумента), то 
вопрос о том, какую из версий функции AREA использовать, должен быть решен во 
время выполнения. Такой способ вызова называют связыванием во время выполнения. 
    6.  Типы ELLIPSE и CIRCLE представляют собой пример простой иерархии 
типов. Конечно, в общем иерархии типов могут иметь произвольную сложность. 
    Иерархии типов иногда называют иерархиями классов (термин "класс" иногда 
используют как синоним термина "тип"), иерархиями обобщения (так как, 
например, эллипс является обобщением окружности), иерархиями специализации 
(так как, например, окружность является специализацией эллипса), иерархиями 
включения (так как множество окружностей является подмножеством множества 
эллипсов) или просто иерархиями ISA. В этой книге будет использоваться термин 
"иерархия типов". 
    7.  Концепцию совместимости типов необходимо несколько пересмотреть и 
расширить для типов, состоящих в одной иерархии. В основном изменения 
заключаются в следующем: 
    • В операции сравнения дев значения А и В не обязательно должны 
принадлежать одному типу. Но если А и В принадлежат разным типам, то эти типы 
должны иметь общий супертип (на некотором уровне иерархии типов). 
    • В операции присвоения А := в значения А и В не обязательно должны 
принадлежать одному типу. Но если А и В принадлежат разным типам, то А должно 
быть супертипом для В (на некотором уровне иерархии типов). 
    8.  Подытожить сказанное можно следующим утверждением. Любой данный член 
определенной иерархии типов автоматически наследует все функции, которые 
применимы к родителю этого члена (и, конечно, такое наследование является 
рекурсивным, т.е. данный член иерархии на самом деле наследует функции, 
которые применяются ко всем предкам данного члена). 
    Тем не менее, подобные функции всегда можно переопределить на любом 
заданном уровне иерархии. Более того, каждый член иерархии может обладать 
собственными функциями, которые не применяются к предкам данного члена. 

    Глава 19. Домены, отношения и типы данных 529 

    Замечание. Возможность применения "одной" функции к данным различного типа 
(точнее, возможность использования для разных типов различных функций с 
одинаковыми именами) называют полиморфизмом. Полиморфизм имеет еще несколько 
названий, в частности родовые функции, экземпляры функций и перегрузка операторов, 

    И последнее соображение. Выше утверждалось, что наследование применяется к 
"свойствам" типов. В случае доменов наследуемыми свойствами являются операторы 
или функции, как описано выше; в случае отношений наследуемыми свойствами 
(принципиально) являются атрибуты рассматриваемого отношения, как будет 
показано в следующем разделе. 

    Отношения 

    Как упоминалось выше, идея наследования имеет смысл как на уровне доменов, 
так и на уровне отношений. Предположим, что отношение ЕМР, содержащее 
информацию о сотрудниках (employees), определено следующим образом: 

    CREATE BASE RELATION EMP { ЕМР#   . . . , ENAME   ... , DEPT#   ... , 
SALARY  . . . ) PRIMARY KEY { EMP# ) ; 

    Теперь предположим, что некоторые сотрудники являются программистами 
(programmer) (и все программисты являются сотрудниками). Тогда можно создать 
базовое отношение PGMR, определение которого показано ниже: 

    CREATE BASE RELATION PGMR ISA ( ЕМР ) { LANG ... ) ; 

    Атрибут LANG содержит информацию о языке программирования, которым владеет 
программист, например С, SQL. Отметим следующее: 
    1. Составной тип данных, соответствующий отношению PGMR, можно 
рассматривать как подтип для (составного) типа данных, который соответствует 
отношению ЕМР. Аналогично, (составной) тип данных, соответствующий отношению 
ЕМР, можно рассматривать как супертип для (составного) типа данных, который 
соответствует отношению PGMR. 
    2.  Инструкцию CREATE BASE RELATION для отношения PGMR можно рассматривать 
(частично) как сокращение следующего определения: 

    CREATE BASE RELATION PGMR ( EMPI    . . . , LANG    . . . ) PRIMARY KEY ( 
EMP# ) FOREIGN KEY ( EMP# ) REFERENCES EMP DELETE CASCADES UPDATE CASCADES ; 

    Другими словами, отношение PGMR обладает в точности двумя собственными 
атрибутами: ЕМР#, который в основном и внешнем ключах ссылается на основной 
ключ отношения ЕМР, и LANG. Кроме того, системе известно (в силу инструкции 
"ISA (EMP) "), что кортеж отношения PGMR имеет не более одного 
соответствующего кортежа в отношении ЕМР и что кортеж отношения PGMR можно 
рассматривать как кортеж, который наследует значения атрибутов ENAME, DEPT# и 
SALARY из соответствующего (уникального) кортежа отношения ЕМР (рис. 19.1). 
Более того, заметьте, что теоретически подтип имеет и супермножество атрибутов. 

    530 Часть V, Дополнительные аспекты 

    
    ЕМР	ЕМР#	ENAME	DEPTft	SALARY 
    El Е2 ЕЗ Е4	Lopez Cheng Finzi Saito	Dl Dl D2 D2	40K 42K 30K 35K 
    <- Нас	ледуется и	з EMP -» 
    POTR	ЕМР#	ENAME	DEPTtt	SALARY	LANG 
    Е2 ЕЗ	Cheng Finzi	Dl D2	42K 30K	С SQL 

    Рис. 19.1. Сотрудники и программисты (образцы данных) 

    3.  Любая функция, работающая с данными о сотрудниках (типа ЕМР), должна 
работать и с данными о программистах. 
    4.   В случае доменов, как описано выше, на уровне подтипов можно 
определять функции с теми же именами, что и на уровне супертипов. Аналогично, 
в случае отношений на уровне подтипов можно определять дополнительные 
атрибуты, которые перекрывают одноименные атрибуты, определенные на уровне 
супертипов. Например, в отношении ЕМР можно определить атрибут HIREDATE (дата 
приема на работу), в котором будет храниться дата приема сотрудника на работу 
в организацию, а в отношении PGMR также можно определить атрибут HIREDATE, в 
котором будет храниться дата зачисления сотрудника на работу в отдел 
программирования. Тогда выражение PGMR.HIREDATE будет ссылаться не на первый, 
а на последний атрибут. (Тем не менее, в отношении PGMR всегда доступна 
возможность переименования первого из двух атрибутов с помощью оператора 
RENAME (см. главу 6).) 
    5.  Повторимся. Иерархии типов могут обладать произвольной сложностью. 
Например, одни программисты могут быть прикладными, а другие— системными. 
Поэтому целесообразно определить два соответствующих подтипа — 
APPLICATION_PROG-RAMMER и SYSTEM_PROGRAMMER — для типа PROGRAMMER, который для 
них является супертипом. Этот процесс можно продолжать рекурсивно на любое 
количество уровней. 

    Множественное наследование 

    Замечание. Эта тема включена в обсуждение исключительно для полноты 
изложения. Здесь не приводится достаточно детальной информации. 

    На протяжении всего предыдущего изложения предполагалось, что каждый 
подтип имеет единственный непосредственный супертип. Тем не менее, некоторые 
авторы предлагают, а некоторые системы иногда и реализуют возможность 
множественного наследования, исходя из того, что "простое наследование" (т.е. 
наследование с единственным родителем) — недостаточно мощная концепция для 
отражения всего богатства ситуаций реального мира. При множественном 
наследовании некоторый тип может являться подтипом одновременно для нескольких 
различных супертипов. Например, тип WHALE (кит) одновременно может являться 
подтипом для типа MAMMAL (млекопитающее) и для типа MARINE_ANIMAL (морское 
животное). Это означает, что каждый отдельный кит наследует все свойства 
млекопитающих и все свойства морских животных (но конечно, некоторые 
млекопитающие не являются морскими животными, а некоторые морские животные не 
являются млекопитающими) (рис. 19.2). 

    Глава 19. Домены, отношения и типы данных 531 

    Между прочим, заметьте, что термин "иерархия типов" не совсем подходит для 
типов с множественным наследованием, поэтому некоторые авторы используют 
термин "структура типов". 

    |	MAMMAL          |                                                        
              |           MARINE_ANIMKL         | |          WHALE       Ч 

    Рис, 19.2. Множественное наследование 

    Множественное наследование обладает одной проблемой — конфликтами имен. 
Эта проблема состоит в том, что различные супертипы данного подтипа могут 
иметь свойства с одинаковыми именами. Более того, подобные свойства могут быть 
семантически эквивалентными, но могут и не быть таковыми. Например, тип 
млекопитающих и тип морских животных могут иметь атрибуты LIFESPAN 
(продолжительность жизни), которые семантически эквивалентны, или атрибуты 
TAIL (хвост), которые имеют разное значение: для млекопитающих — наличие, для 
морских животных — длина, следовательно, эти атрибуты не являются семантически 
эквивалентными). Поэтому возникает необходимость в механизме обработки 
подобных ситуаций. 
    Другой, более общей проблемой множественного наследования является наличие 
нескольких различных интерпретаций этой концепции. Например, рассмотрим 
ситуацию, представленную на рис. 19.3. Здесь некоторые сотрудники работают 
полный день, а некоторые — только часть дня. Кроме того, существуют также и 
программисты, работающие полный день и часть дня (отношение PGMR), а также 
секретари, работающие полный день и часть дня (отношение SECY). Эта ситуация 
отличается от рассмотренной на рис. 19.2 тем, что, например, программист может 
наследовать свойства сотрудника, работающего полный день, или сотрудника, 
работающего часть дня, но не обоих названных типов. 

    ["      ЕМР    "| 
    ________________	I            _______________ 
    |	FULLJTIME        I                                                       
             |        PART_TIME     ] 
    п____	
    .___.	;   i 
    I_____PGMR____I	I_____SECY           | 

    Рис, 19,3. Множественное наследование (другой пример) 


    19.5. Атрибуты, значениями которых являются отношения 

    Выше в этой главе уже упоминалось, что скаляры могут обладать структурой 
произвольной сложности, если их рассматривать на более низких уровнях 
абстракции. Также отмечалось, что скаляры могут являться отношениями. Другими 
словами, можно определить домены и, следовательно, атрибуты, значениями 
которых являются отношения. Поэтому можно создавать отношения, которые 
содержат внутри себя 

    532	Часть V, Дополнительные аспекты 

другие отношения (и т.д. рекурсивно, произвольное количество раз). В этом 
разделе мы отвлечемся для краткого обсуждения этой идеи. 

    Замечание. Дальнейшее обсуждение в основном построено на материале 
публикации [19.3], из которой читатель может получить дополнительную информацию. 

    На рис. 19.4 показан пример отношения с атрибутами, значения которых 
являются отношениями. (Далее для обозначения подобных атрибутов будет 
использоваться термин RVA-атрибут, от англ. Relation-Valued Attribute.) Сразу 
же следует заметить, что пустое множество деталей, поставляемых поставщиком 
S5, представлено в этом отношении пустым множеством (точнее, пустым 
отношением), а не каким-то плохо обдуманным значением NULL, как в случае 
моделирования подобного отношения с помощью внешнего соединения поставщиков и 
партий товаров по атрибуту S#. На практике получается, что RVA-атрибуты лучше 
приспособлены к решению задач с помощью внешних соединений. Действительно, 
оператор внешнего соединения в его классическом смысле вообще не нужен в 
системах, которые поддерживают RVA-атрибуты. 
    
    S_SP	s#	SNAME	STATUS	CITY		PQ 
    
    
    SI	Smith	20	London		P#	OTY 
    PI Pi Ы	300 200 100 
    
    
    S2	Jones	10	Paris		P#	QTY 
    PI P2	300 400 
    
    
    
    
    S5	Adams	30	Athens		P#	QTY 
    
    
    Рис. 19.4. Пример отношения с атрибутами, значениями которых являются отношения 

    Абсолютно точно нужно понимать и следующее утверждение. Значения атрибута 
PQ на рис. 19.4 действительно являются отношениями, но эти значения (как все 
значения атрибутов) инкапсулированные. Это означает, что СУБД и пользователь 
не могут одновременно заглядывать "внутрь" этих значений и просматривать 
другие атрибуты представленного на рис. 19.4 отношения. Отношение S_SP не 
нарушает требований реляционной нормализации. 
    В отличие от изложенной выше концепции, различными исследователями (см. 
[19.6, 19.7, 19.9]) была предложена концепция вложенных отношений, которая 
нарушает требования нормализации. Действительно, вложенные отношения часто 
называют "ЫР2-отношениями", где NF2= NFNF= "Non First Normal Form" ("не первая 
нормальная форма"); это означает, что подобные отношения не нормализованы по 
определению. (С другой стороны, отношение S_SP находится в первой нормальной 
форме.) Атрибуты во вложенных отношениях могут принимать значения, которые 
являются отношениями (см. рис. 19.4), но не являются инкапсулированными. 
Поэтому вложенные отношения требуют внесения значительных дополнений и 
изменений в реляционную алгебру, в частности включая новые операции NEST и 
UNNEST для преобразований вложенных отношений в обычные и обратно. Ниже 
приведены описания данных операций. 

    Глава 19. Домены, отношения и типы данных 533 

    •  Получая отношение и набор атрибутов, операция NEST возвращает 
соответствующее вложенное отношение. Например, результатом вложения 
(выполнения операции NEST) отношения с данными о поставщиках по атрибутам S#, 
SNAME и STATUS будет отношение, которое содержит три кортежа, по одному для 
каждого значения атрибута CITY (London, Paris, Athens). Каждый из этих 
кортежей содержит соответствующее название города и отношение с атрибутами 
{S#, SNAME, STATUS}, которое содержит данные о поставщиках в выбранном городе. 
    •  Операция UNNEST противоположна операции NEST. Если выполнить разложение 
(операцию UNNEST) отношения R по некоторому множеству атрибутов, а затем 
вложение результата предыдущей операции по тому же множеству атрибутов, то мы 
не обязательно получим исходное отношение R. (См. комментарий к [19.9], 
который содержит дополнительный пример и более детальное обсуждение.) 
    Предложения [19.3], наоборот, касаются относительно небольших изменений в 
операторе EXTEND (для обеих NEST- и ишкзт-подобных операций). 
    Мы не ставили целью детальное обсуждение значений, являющихся отношениями. 
Поэтому в завершение приведем лишь краткий список преимуществ, которые 
обеспечивает надежная поддержка RVA-атрибутов. 
    •   Как упоминалось выше, RVA-атрибуты снимают потребность в операции 
внешнего соединения. 
    •  RVA-атрибуты решают некоторые проблемы операции SUMMARIZE с нулевыми 
значениями (см. [6.3]). 
    •   RVA-атрибуты решают некоторые проблемы операции DIVIDE с нулевыми 
значениями (см, [6.4]), 
    •   RVA-атрибуты значительно упрощают некоторые "сложные" запросы. 
    •   RVA-атрибуты служат идеальным инструментом для моделирования некоторых 
видов "сложных" данных (другими словами, в исключительных ситуациях хотелось 
бы включить RVA-атрибуты даже в базовые отношения). 

    19.6. Поддержка SQL 

    Этот раздел включен в изложение только для полноты материала книги. Дело в 
том, что стандарт SQL не поддерживает ни одной из рассмотренных в данной главе 
идей. Чтобы вспомнить, какие возможности предоставляет SQL в данной области, 
обратитесь к главе 8. 

    19.7. Резюме 

    В этой главе обсуждались основные аспекты доменов, отношений и типов 
данных. Во-первых, домен это не что иное, как тип данных, точнее, скалярный 
тип данных, возможно системный, но в более общем случае — определяемый 
пользователем тип данных с потенциально произвольной сложностью внутренней 
структуры. Во-вторых, отношение не является типом данных как таковым, но, 
конечно, отношение принадлежит к типу, а именно составному типу "множество 
кортежей", где кортежи, в свою очередь, также принадлежат к составному типу, а 
именно типу, который указан заголовком отношения. И заметьте, что данное 
утверждение относится ко всем отношениям, как к порожденным, так и к базовым. 
    Еще несколько слов о доменах. Представление любого данного домена 
определено в терминах уже существующих доменов — либо встроенных в систему, 
либо определенных пользователем. После определения нового домена (или на более 
поздних стадиях разработки) должны быть определены операции или функции для 
работы со значениями из данного домена (в частности, операции для создания 
"лите

    534	Часть V, Дополнительные аспекты 

ралов", принадлежащих рассматриваемому домену). Следовательно, СУБД точно 
"знает", какое скалярное выражение корректно, и для корректных выражений 
система может точно определить домен результата. В частности, система может 
определить домен порожденных атрибутов, которые появляются в результатах 
операций EXTEND и SUMMARIZE'. В данной главе также обсуждался синтаксис и 
семантика инструкций CREATE DOMAIN И DESTROY DOMAIN. 
    Теперь об отношениях. В этой главе мы не стали обсуждать вопрос 
определения операций на отношениях, так как различные подобные операции (в 
частности, операции реляционной алгебры, включая определенные операторы 
присвоения, обновления и сравнения (см. главу 6)) уже хорошо известны читателю 
и встроены во многие системы. Более того, подобные операции достаточно 
характерны в том смысле, что они применяются ко всем отношениям. Тем не менее, 
если система предоставляет необходимые средства, то автор не видит причин, 
препятствующих дополнению подобных встроенных операций набором операций, 
определяемых пользователем и специфических для определенных отношений. В 
некотором отношении подобными операциями можно считать любую конкретную 
прикладную программу. (Единственное исключение состоит в том, что такие 
"операции" нельзя включать в выражения, использующие основные реляционные операции.) 
    Далее, некоторые операции (в частности, некоторые операции сравнения, а 
следовательно, некоторые реляционные операции, такие как операция объединения) 
требуют, чтобы их операнды (будь то скаляры, кортежи или отношения) были 
совместимыми по типу. Совместимость по типу также должна соблюдаться для 
источника и приемника операций присвоения. Совместимость по типу означает, что 
либо два типа идентичны, либо существует такая известная системе функция 
преобразования, что один из типов может быть преобразован в другой. Еще раз 
обратите внимание, что данная концепция применяется как на уровне доменов, так 
и на уровне отношений. 
    Затем обсуждался вопрос подтипов и супертипов и связанные с ним вопросы 
наследования и иерархий типов (также вкратце были изложены возможности 
множественного наследования и структур типов). Все названные концепции 
распространяются как на домены, так и на отношения. 
    •   Во-первых, если домен Y определен как подтип домена X, то любая 
функция, которая применяется к экземплярам домена X, обязательно применима к 
экземплярам домена Y (хотя, возможно, на домене Y подобные функции потребуется 
переопределить). Кроме того, могут существовать функции, которые применимы к 
экземплярам домена Y и не применимы к экземплярам домена X. 
    •   Во-вторых, если базовое отношение Y определено так, что его тип 
является подтипом типа базового отношения X, то любой атрибут отношения X 
можно также рассматривать как неявный атрибут отношения Y. Кроме того, базовое 
отношение Y может обладать собственными атрибутами, которые не принадлежат 
отношению X. 
    В обоих случаях подтип обладает супермножеством. 
    Замечание. Не путайте понятия иерархии типов и иерархии представления. 
Другими словами, из того что, например, значения в доменах POINT и ELLIPSE 
представляются с помощью двух чисел типа FLOAT, не следует, что один из типов 
является подтипом другого. Аналогично, из того что CIRCLE является подтипом 
ELLIPSE, не следует, что представление первого из доменов является 
подмножеством представления второго. 
    1 Заметьте, что операция SUMMARIZE использует некоторые агрегативные 
функции (COUNT, SUM и т.п.), т.е. функции, которые возвращают скалярные 
значения, но получают в качестве одного из аргументов целые отношения. Поэтому 
возникает необходимость в механизме, который позволяет определять такие функции. 

    Глава 19. Домены, отношения и типы данных	535 

    После этого было приведено краткое обсуждение идеи атрибутов, значениями 
которых являются отношения (RVA-атрибутов). Утверждалось, что RVA-атри-буты 
при корректной реализации не нарушают требований реляционной нормализованное™ 
Корректной реализации RVA-атрибутов (т.е. реализации, которая не нарушает 
требований реляционной нормализации) была противопоставлена поддержка 
вложенных отношений (которая нарушает требования нормализации). Были также 
указаны некоторые преимущества корректной реализации RVA-атрибутов. 
    И наконец, было отмечено, что стандарт SQL в теперешней его форме не 
поддерживает ни одну из идей, обсужденных в этой главе. 

    Упражнения 

    19.1. Дайте определения следующим терминам: совместимость по типу; 
приведение; инкапсуляция; строгая типизация; конструктор типов; подтип, 
супер-тип; наследование; подстановка; полиморфизм; совместимость по 
объединению; отмена проверки домена. 
    Почему два последних термина использовать не желательно? 
    19.2. Создайте запрос, требующий "отмены проверки домена", в контексте 
базы данных поставщиков, деталей и проектов. 
    19.3. Какие из указанных ниже выражений в контексте базы данных 
поставщиков, деталей и проектов будут корректны в системе, поддерживающей 
строгую типизацию в изложенном в этой главе смысле? Для корректных выражений 
укажите домен результата: 

    а) J.CITY = P.CITY 
    б)  JNAME   | |   PNAME 
    B) QTY + 100 Г) QTY * 100 Д) P.COLOR = P.CITY 
    C)  J.CITY < P.CITY 
    Ж)  J.CITY = P.CITY   ||    'burg' 

    19.4. Детально опишите влияние на операции обновления неявного указания 
внешнего ключа в примере EMP-PGMR в разделе 19.4. 
    19.5. Воспользовавшись синтаксисом, приведенным в этой главе, определите 
тип данных прямоугольник (rectangle) и квадрат (square), где квадрат является 
подтипом прямоугольника. Для простоты предположите, что стороны 
прямоугольников могут располагаться только вертикально или горизонтально 
относительно осей координат. Запишите ответ а) в терминах доменов RECTANGLE и 
SQUARE; б) в терминах базовых отношений RECTANGLE и SQUARE. 
    19.6. Рассмотрите "структуру типов", показанную на рис. 19.3. Здесь можно 
избежать очевидной необходимости использования множественного наследования (а 
значит, можно преобразовать структуру типов в иерархию типов). Сделать это 
можно, определив единственный супертип (ЕМР) и четыре непосредственных 
подтипа, представляющих программистов с полной занятостью, программистов с 
частичной занятостью, секретарей с полной занятостью и секретарей с частичной 
занятостью. Есть ли недостатки в этой идее? 
    19.7. Какая поддержка каталога необходима для обеспечения строгой типизации? 
    19.8. Какая поддержка каталога необходима для обеспечения наследования типов? 

    536	Часть V. Дополнительные аспекты 


    Список литературы 

    19.1. Cleaveland J.C. An Introduction to Data Types.— Reading, Mass.: 
Addison-Wesley, 1986. 
    19.2. Codd E.F. Extending Relational Database Model to Capture More 
Meaning // ACM TODS. — 1979. —4, № 4. 
    Работа Кодда по расширенной версии реляционной модели, известной как RM/T, 
включает обсуждение использования отношений (но не доменов) для представления 
подтипов и супертипов. В работе также обсуждаются вопросы множественного 
наследования и реализации (в частности, вопросы конструкции каталога). 
Замечание. Работы [5.1] и [12.5] также ссылаются на данную публикацию. 
Дополнительную информацию можно найти в комментариях к названным работам. 
    19.3. Darwen H. Relation-Valued Attributes // CJ. Date and Hugh Darwen. 
Relational Database Writings 1989-1991. — Reading, Mass.: Addison-Wesley, 1992. 
    19.4. Date C.J. What Is a Domain? // C.J. Date. Relational Database 
Writings 1985-1989. — Reading, Mass.: Addison-Wesley, 1990. 
    Как сказано в комментариях к [4.8], данная работа представляет собой 
попытку создания систематического и исчерпывающего учебного пособия по 
концепции реляционных доменов. В ней определены следующие аспекты поддержки 
доменов (перечисленные возможности необходимы, но не достаточны для того, 
чтобы назвать СУБД поддерживающей домены в полном объеме): 
    • Оператор определения нового домена (позволяющий указать, по крайней 
мере, имя и внутреннее представление домена). 
    • Возможность указания соответствующего домена для каждого атрибута 
каждого базового отношения. 
    • Операторы удаления и изменения доменов. 
    • Условия целостности на уровне доменов. 
    • Поддержка соответствующих литералов. 
    • Соответствующие правила преобразования и приведения типов, включая 
правила наследования определенного типа данных. 
    • Возможность указания операторов, которые применяются к каждому домену 
или комбинации доменов. 
    • Соответствующая поддержка каталога для всех перечисленных выше возможностей. 
    В данной работе также представлен обширный список преимуществ корректной 
поддержки доменов. 
    19.5. DeMichiel L.G., Chamberlin D.D., Lindsay B.G., Agrawal R., Arya M. 
Polyglot: Extensions to Relational Databases for Sharable Types and Functions 
in Multi-Language Environment // IBM Research Report RJ8888. — 1992. 
    Выдержка из введения: "Polyglot — это расширяемая система типов для 
реляционной базы данных. Эта система поддерживает наследование, инкапсуляцию и 
динамический вызов методов". (Динамический вызов методов — это еще один термин 
для обозначения связывания во время выполнения.) Продолжим цитирование: 
"Polyglot позволяет использовать несколько языков программирования и дает 
возможность объектам сохранять свое поведение при пересечении границы между 
базой данных и прикладной программой. Эта работа описывает внутреннее строение 
системы Polyglot,

    Глава 19. Домены, отношения и типы данных	537 

расширения в языке SQL, поддерживающие типы и методы системы Polyglot, и 
реализацию этой системы в прототипе реляционной базы данных Starburst", 
    Система Polyglot является решением для групп вопросов, рассмотренных в 
данной главе. Тем не менее, уместно сделать несколько пояснений. Во-первых, 
реляционный термин домен (неожиданно) никогда не употребляется. Во-вторых, 
Polyglot предоставляет встроенные конструкторы типов (в системе Polyglot их 
называют метатипами); базовый тип, тип-кортеж, тип-переименование, тип-массив 
и языковой тип, но (опять неожиданно) не представлен конструктор типов 
тип-отношение. Тем не менее, система предоставляет возможность создания новых 
конструкторов типов. 
    19.6. Jaeschke G., Schek H. Remarks on the Algebra of Non Normal Form 
Relations // ACM SIGACT-SIGMOD Symposium on Principles of Database Systems. — 
Los Angeles, Calif, 1982. 
    Приведено исследование вложенных отношений. В работе обсуждаются 
отношения, вложенные не более как еще на один уровень (т.е. отношения обладают 
атрибутами со значениями, являющимися множествами, элементы которых нельзя 
больше разбивать на составные части). В работе представлены оригинальные 
версии операторов NEST и UNNEST. 
    19.7. Makinouchi A. A Consideration of Normal Form of 
Not-Necessarily-Normalized Relations in the Relational Data Model // Proc. 3rd 
Intern. Conf. on Very Large Data Bases. — Tokyo, Japan, 1977. 
    Макинучи является первым из исследователей, которые серьезно изучали идею 
вложенных отношений. 
    19.8. Osborn S.L., Heaven Т.Е. The Design of a Relational Database System 
with Abstract Data Types for Domains //ACM TODS. — 1990. — 11, № 3. 
    В этой публикации описан экспериментальный прототип (только частично 
реализованный в момент написания этой работы), известный под названием RAD. 
Этот прототип поддерживает определение новых абстрактных (т.е. определяемых 
пользователем) типов данных, подобных абстрактным типам данных, которые 
описаны в настоящей главе. Приведенный ниже синтаксис инструкции CREATE DOMAIN 
(версия прототипа RAD) дает некоторое представление о возможностях этой 
системы (для более детального ознакомления обратитесь к данной работе). 
    CREATE DOMAIN домен AS 
    OUTPUT	IS процедура INSERT IS процедура UPDATE IS процедура CONSTANTS ARE 
процедура EQUAL IS процедура LESSTHAN IS процедура PREDICATES ARE список-элементов-через-запятую 
    19.9. Roth M.A., Korth H.F., Silberschatz A. Extended Algebra and Calculus 
for Nested Relational Databases // Ibid. — 1988. — 13, № 4. 
    В работе определены алгебра и исчисление для произвольных вложенных 
отношений и показана их эквивалентность. Замечание. В этой публикации явно 
отрицается возможность существования атрибутов, значениями которых являются 
пустые отношения (см, ниже). Тем не менее, как уже упоминалось в тексте данной 
главы, именно такая возможность необходима для корректного представления 
некоторых видов внешних связей. 

    538 Часть V. Дополнительные аспекты 

    В тексте главы было сделано замечание относительно обратимости операций 
NEST и UNNEST. Если вложить отношение R по некоторому набору атрибутов, то 
всегда существует обратная операция раскладки, в результате которой будет 
получено исходное отношение R. Тем не менее, если разложить (вложенное) 
отношение R по некоторому набору атрибутов, то обратная операция вложения, в 
результате которой будет получено исходное отношение R, может либо 
существовать, либо нет. Ниже приведен пример, который базируется на примере из 
[19.3]. Предположим, что дано вложенное отношение TWO, которое показано на 
рисунке ниже, и это отношение разложено по атрибуту RVX, в результате чего 
получено отношение THREE. Если же вложить отношение THREE по атрибуту X (и 
назвать полученный атрибут RVX), то будет получено отношение TWO, а не ONE. 

    TWO _A__	RVX                             THREE _A__   X___                 
 ONE _A__            RVX________ 
    ~~~~~~1        ~а	______ 1                _Х__                             
               1           Ь                                        1          
      _Х____ 
    а	1__ с а _Ь__ Ь __ с 
    1	X                                                                        
                        ________________ а с 

    Заметьте, что в отношении ONE атрибут RVX функционально зависит от 
атрибута А, поэтому А является потенциальным ключом. Если теперь разложить ONE 
по атрибуту RVX, то мы получим отношение THREE, которое, как уже было 
показано, можно вложить так, чтобы получить отношение ONE. Таким образом, для 
данной пары отношений операции NEST и UNNEST взаимообратимы. В более общем 
случае для определения обратимости этих операций можно сформулировать правило, 
которое гласит: отношение R с атрибутом RVX, значениями которого служат 
отношения, является обратимо разлагаемым по атрибуту RVX тогда и только тогда, 
когда выполняются приведенные ниже требования. 
    • Ни один из кортежей в R не содержит пустого отношения в качестве 
значения атрибута RVX. 
    • Атрибут RVX функционально зависит от множества остальных атрибутов 
отношения R. Другими словами, в отношении R должен существовать некоторый 
потенциальный ключ, не содержащий атрибута RVX. 
    19.10. Stonebraker M. Inclusion of New Types in Relational Data Base 
Systems // Proc. 2nd Intern. Conf. on Data Base Engineering. — Los Angeles, 
Calif, 1986. 
    В работе описан набор расширений для прототипа системы INGRES, 
предназначенных для поддержки следующих возможностей: 
    • определение новых типов; 
    • определение операторов для подобных типов; 
    • определение новых структур хранения и методов доступа для новых типов; 
    • оптимизация выражений, использующих данные новых типов и новые операторы. 

    Глава 19. Домены, отношения и типы данных 539 

    19.11. Stonebraker M.,  Anton J,,  Hanson E.  Extending a Database  System 
 with Procedures // ACM TODS. — 1987. — 12, № 3. 
    В этой публикации предложено рассматривать "процедуры базы данных" (т.е. 
семейства операций базы данных или, возможно, целые программы на языках 
профаммирования общего назначения) как типы данных. Таким образом, атрибуты 
отношений могут включать и подобные процедуры. В качестве тривиального примера 
можно привести расширение атрибутом PARTS отношения S с данными о поставщиках. 
Значением атрибута PARTS для поставщика S1 будет значение следующего запроса 
на языке QUEL: 

    RETRIEVE ( SP.P#, SP.QTY ) WHERE SP.S# = "SI" 

    Для выполнения подобных процедур предусмотрен новый оператор EXECUTE. В 
данном примере эффект выполнения этой процедуры состоит в том, чтобы 
предоставить пользователю возможность рассматривать кортеж S1 как 
ненормализованный, так как (концептуально) этот кортеж теперь содержит обычную 
информацию о поставщике (атрибуты S#, SNAME, STATUS и CITY) вместе с 
повторяющейся группой атрибутов, описывающих детали (атрибуты Р# и QTY). 
Заметьте, что это лишь другой подход к идее "вложенных отношений" (см. [19.3, 
19.6, 19.7, 19.9]). 
    В работе утверждается, что типы данных, определяемые пользователем, в 
смысле, изложенном, например, в [19.4, 19.8], полезны для поддержки 
относительно простых объектов, которые не имеют общих составных частей (или 
подобъектов), но процедуры баз данных являются лучшим решением для сложных 
объектов. Конечно, одно из преимуществ процедур состоит в том, что большинство 
СУБД уже обладает некоторыми обозначениями для записи процедур: например, 
представления можно рассматривать как простейшие процедуры, так же как 
процедуры можно рассматривать и хранимые процедуры базы данных. Таким образом, 
трактовка подобных процедур как "полноправных объектов" (это термин, 
используемый в данной публикации) позволяет в едином стиле трактовать 
различные возможности СУБД и избавляет от необходимости считать подобные 
возможности чем-то специальным и несистематическим. Среди других достоинств 
подобного подхода можно отметить наличие поддержки некоторых возможностей 
"семантических" и (или) объектно-ориентирован ных СУБД, не нарушающей каноны 
реляционной модели. 
    В публикации представлена расширенная версия языка QUEL системы INGRES, 
называемая QUEL+. В этой версии реализованы все перечисленные выше идеи. Язык 
QUEL+ реализован в расширенной версии INGRES+ прототипа системы INGRES. В 
работу также включены результаты эталонного тестирования, которые показали, 
что производительность прототипа INGRES+ достаточно хорошо конкурирует с 
производительностью оригинальной версии прототипа INGRES. Кроме того, 
высказываются некоторые соображения по поводу повышения производительности. 
    19.12. Stonebraker M., Anderson E., Hanson E., Rubinstein В. QUEL as a 
Data Type. // Proc. ACM SIGMOD Intern. Conf. on Management of Data. — Boston, 
Mass, 1984. 
    Более ранняя версия работы [19.11]. 

    Ответы к некоторым упражнениям 

    19.1. Термин "совместимость по объединению" запрещено использовать, так 
как, во-первых, он не совсем подходящий и, во-вторых, не совсем точно отражает 
смысл понятия (этот термин по-разному определяется в разных языках, в 

    540	Часть V, Дополнительные аспекты 

    разных системах и разными авторами). Термин "отмена проверки домена" не 
используется, так как уже не используется сама концепция. 
    19.2. Примером может послужить запрос "Получить все детали, номера которых 
имеют такое же символьное представление, что и некоторые номера проектов". 
    19.3. а) корректное (домен результата Boolean); б) возможно, некорректное, 
в зависимости от того, определен ли оператор "ц" как корректный для домена 
NAME; в) корректное (результат типа QTY); г) корректное (результат типа QTY), 
но оба выражения (данное и предыдущее) могут давать результаты, которые 
нарушают некоторые условия домена; д) возможно, некорректное; е) корректное, 
если предположить, что оператор "<" определен для домена CITY (тип результата 
Boolean); ж) возможно, некорректное (корректным будет выражение J.CITY = 
CHAR(P.CITY) 11 "burg"). 
    19.4. Для отношения ЕМР: а) обновление ЕМР# приведет к каскадному 
обновлению атрибута ЕМР# в соответствующем кортеже отношения PGMR (если такой 
кортеж существует); б) удаление кортежа из отношения ЕМР приведет к удалению 
соответствующего кортежа из отношения PGMR (если такой кортеж существует). Для 
отношения PGMR: а) вставка кортежа в отношение PGMR завершится неудачей, если 
не существует соответствующего кортежа в отношении ЕМР; б) обновление атрибута 
ЕМР# завершится неудачей, если в отношении ЕМР не существует кортежа с новым 
значением атрибута ЕМР#. Заметьте, что вставка кортежа в отношение PGMR не 
требует указания значений атрибутов ENAME, DEPT# и SALARY. Более того, было бы 
неправильно позволять непосредственно обновлять эти унаследованные атрибуты 
(было бы странно иметь возможность обновлять атрибуты, не имея возможности 
вставлять новые значения). Тем не менее, существует возможность определения 
соединения ЕМР JOIN PGMR, например как представления V, которое (теоретически) 
подде рживает подобные операции INSERT и UPDATE. 
    19.5. a) CREATE DOMAIN RECTANGLE REP (A POINT, В POINT) ; 
    I* А и В являются нижним левым и верхним правым углами */ /* 
прямоугольника, показанные ниже функции нарушают */ /* инкапсуляцию домена 
RECTANGLE */ 
    /* функция определения прямоугольника */ CREATE FUNCTION RECTANGLE ( A 
POINT, В POINT ) 
    RETURNS ( RECTANGLE ) ; AS BEGIN ; 
    DECLARE R RECTANGLE ; R.A := A ; R.B := В ; RETURN ( R ) ; END ; 
    /* функция получения нижнего левого угла */ 
    CREATE FUNCTION BL ( R RECTANGLE ) RETURNS ( POINT ) 

    Глава 19. Домены, отношения и типы данных	541 

    AS BEGIN ; 
    RETURN ( R.A ) ; 
    END ; 
    /* функция получения верхнего правого утла */ CREATE FUNCTION TR ( R 
RECTANGLE ) RETURNS ( POINT ) AS BEGIN ; 
    RETURN ( R.B ) ; END ; 
    /* Показанное ниже выражение транспонирует прямоугольник R */ R := 
RECTANGLE ( BL( R ), 
    POINT ( X(BL(R)) + Y(TR(R» - Y(BL(R)), 
    Y(BL(R)) +X(TR(R)) -X(BI,(R)) ) ) ; 
    /* определение домена SQUARE */ 
    CREATE DOMAIN SQUARE REP ( BL POINT, TR POINT ) 
    ISA ( RECTANGLE ) ; 
    CREATE FUNCTION IS_SQUARE ( R RECTANGLE ) RETURNS ( BOOLEAN ) /* оператор 
для проверки прямоугольника на "квадратность", */ /* эта функция не нарушает 
инкапсуляцию */ AS BEGIN ; 
    IF X(TR) - X(BL) = Y(TR) - Y(BL) THEN RETURN ( true ) ; ELSE RETURN ( 
false ) ; END; 
    6) CREATE BASE RELATION RECTANGLE ( BL DOMAIN ( POINT ), 
    TR DOMAIN ( POINT ) ) CANDIDATE KEY ( BL, TR ) ; 
    CREATE BASE RELATION SQUARE ISA ( RECTANGLE; ) ; /* Можно добавить 
несколько новых атрибутов */ 
    19.6, Одним из недостатков будет тот факт, что свойства, определяемые 
только для программистов или только для секретарей, нужно будет определять в 
двух местах вместо одного. Аналогична ситуация и с сотрудниками с полной и 
частичной занятостью. 

    542 Часть V. Дополнительные аспекты 

