- •20.7. Средства sql
- •20.8. Резюме
- •21.1. Введение
- •21.2. Некоторые аспекты технологам поддержки принятия решений
- •21.3. Проектирование базы данных поддержки принятия решений
- •21.5. Хранилища данных и магазины данных
- •21.6. Оперативная аналитическая обработка
- •21.7. Разработка данных
- •21.8. Резюме
- •22.1. Введение
- •22.2. Хронологические данные
- •22.3. Основная проблема хронологических баз данных
- •22.4. Интервалы
- •22.5. Интервальные типы
- •22.6. Скалярные операторы для интервалов
- •22.7. Операторы обобщения для интервалов
- •22.8. Реляционные операторы для обработки интервалов
- •22.9. Ограничения, включающие интервалы
- •22.10. Операторы обновления, включающие интервалы
- •22.11. Проектирование базы данных
- •22.12. Резюме
- •23.1. Введение
- •23.2. Обзор основных концепций
- •23.3. Исчисление высказываний
- •23.4. Исчисление предикатов
- •23.5. Базы данных с точки зрения доказательно-теоретического подхода
- •23.6. Дедуктивные субд
- •23.7. Обработка рекурсивных запросов
- •23.8. Резюме
- •Часть VI
- •24.1. Введение
- •24.2. Объекты, классы, методы и сообщения
- •24.3. Еще раз об объектах и объектных классах
- •Cdo для класса set (ref(emp))
- •24.4. Простой пример
- •1 | Course с001 , с001 0ffs , с001 ny offs |
- •24.5. Дополнительные аспекты
- •24.6. Резюме
- •25.1. Введение
- •X2 rational, y2 rational ) ... ;
- •25.2. Первая грубейшая ошибка
- •25.3. Вторая грубейшая ошибка
- •25.4. Вопросы реализации
- •25.5. Преимущества реального сближения двух технологий
- •25.6. Резюме
Cdo для класса set (ref(emp))
Рис. 24.4. Пример экземпляров объектов классов DEPT и ЕМР
Теперь рассмотрим объект DEPT, расположенный в центре рисунка с идентификатором (OID) ddd, который содержит перечисленные ниже объекты.
Неизменяемый объект ' D01' (символьная строка) в открытой переменной экземпляра DEPTi
Неизменяемый объект 'Mktg' (другая символьная строка) в открытой переменной экземпляра DNAMEt
Неизменяемый объект '$1 ООО ООО' (другая символьная строка) определенного пользователем класса MONEY в открытой переменной экземпляра BUDGET
Идентификатор еее изменяемого объекта определенного пользователем класса ЕМР в открытой переменной экземпляра MGR (это идентификатор объекта, представляющего менеджера отдела)
Идентификатор sss изменяемого объекта определенного пользователем класса SET(REFjEMP)) в открытой переменной экземпляра EMPS, которая подробнее описана ниже
Две закрытые переменные экземпляра, содержащие идентификатор (OID) ddd объекта DEPT и идентификатор соответствующего объекта, определяющего класс
Объект с идентификатором sss состоит из набора идентификаторов индивидуальных (изменяемых) объектов класса ЕМР, а также обычных закрытых переменных экземпляра.
На рис. 24.4 экземпляры объектов представлены в том виде, в котором они реально существуют, т.е. на рисунке отображается компонент структуры данных "объектной модели", что позволяет яснее представить саму объектную модель. Обычно в книгах или документации такие диаграммы не используются; вместо этого данные представляются так, как на рис. 24.5, на более высоком уровне абстракции, что, как принято считать, облегчает понимание объектной модели.
DEPT:
DEPT#: D01 DNAME: Mktg
BUDGET: MGR: I
$1 000 000
EMP#: E001 ENAME: Smith
SALARY: POSITION:
$50 000
job
EMPS:
I
EMP#: E001 ENAME: Smith
SALARY: POSITION:
$50 000
job
Puc. 24.5. Пример представления экземпляров объектов DEPT и ЕМР в соответствии с иерархией их вложения
Приведенная на рис. 24.5 схема в большей степени согласуется с интерпретацией на основе иерархии вложения. Однако в ней остается скрытым важный факт; в объектах часто содержатся не собственно другие объекты, а их идентификаторы. Например, согласно рис. 24.5 можно предположить, что объект класса DEPT для отдела с номером 'D01' содержит два экземпляра объекта класса ЕМР для сотрудника с номером 'Е001' (при этом, помимо всего прочего, может получиться, что сотрудник с номером ' Е001' получает две различные зарплаты). Такая ситуация может привести к путанице, поэтому предпочтение следует отдавать схемам, подобным приведенной на рис. 24.4.
В дополнение к этому следует заметить, что реальные объектные определения данных способствуют возникновению запутанных ситуаций, поскольку переменные экземпляра в них обычно определяются не на основе "ссылок" (как в приведенных выше выражениях с использованием гипотетического синтаксиса), а на основе непосредственного отображения иерархии вложения. Например, переменные экземпляра EMPS в объектном классе DEPT обычно определяются не как REF(SET(REF(EMP))), а в более краткой форме: SET (ЕМР). Несмотря на некоторую громоздкость полной записи, мы все же предпочитаем наш стиль, как более ясный и точный.
Следует отметить, что вся прежняя критика иерархического подхода (например, иерархии вложения, воплощенной в СУБД IMS) в основном относилась именно к иерархиям вложения. Подробное рассмотрение данного вопроса заняло бы слишком много места, поэтому достаточно сказать, что основным аргументом такой критики было отсутствие симметрии. В частности, иерархии не совсем удобны для представления отношений типа "многие ко многим". Например, для рассматриваемого ранее отношения поставщиков и деталей может возникнуть вопрос, содержатся ли объекты-поставщики в объектах-деталях или наоборот. А может, верно и то, и другое? А что можно сказать об отношениях поставщиков, деталей и проектов?
Действительно, подобных вопросов больше, чем можно было бы предположить. С одной стороны, как мы убедились, объекты представляют собой иерархию, и к ним также относятся привычные критические замечания относительно иерархий. А с другой стороны, как явствует из рис. 24.4, такие объекты на самом деле образуют не иерархию, а кортежи с перечисленными ниже компонентами.
Неизменяемые "подобъекты", т.е. самоидентифицируемые значения, такие как целые числа и денежные суммы.
Идентификаторы изменяемых "подобъектов", т.е. ссылки или указатели на другие (возможно, совместно используемые) изменяемые объекты.
Множества, списки, массивы и т.д. объектов, перечисленных в пп. 1, 2 и в этом пункте.
К этому списку следует также добавить скрытые идентификаторы объектов, идентификаторы объектов, определяющих классы, и т.д. В частности, обратите внимание на п. 3: обычно объектные системы поддерживают несколько "коллекций" генераторов типов (SET, LIST, ARRAY и др.), но обычно не поддерживают тип RELATION (отношение). Такие генераторы могут сочетаться сколь угодно сложно. Например, массив списков пакетов массивов указателей на целые переменные может составлять при определенных условиях отдельный изменяемый объект. В следующем подразделе мы продолжим обсуждение этого вопроса.
Еще раз об идентификаторе объекта
Чтобы сослаться на объект или идентифицировать его, в современных реляционных СУБД обычно используются ключи, определяемые и управляемые пользователями (далее для краткости будем называть их пользовательскими ключами), хотя, как нам известно из главы 3, в реляционных базах данных указатели наподобие идентификаторов объектов фактически намеренно запрещены. Также хорошо известно, что применение пользовательских ключей сопряжено с некоторыми проблемами. Эти проблемы достаточно подробно рассматриваются в [13.10] и [13.16], где сделан вывод, что реляционные СУБД, по крайней мере в качестве альтернативы, должны поддерживать и ключи, определяемые системой ("суррогатные"). Аргументы в пользу идентификаторов объектов в объектных системах подобны аргументам в пользу суррогатных ключей в реляционных системах. (Однако их не следует приравнивать друг к другу, поскольку суррогатные ключи — это доступные пользователю значения, а идентификаторы объектов — это адреса или указатели, которые, по крайней мере концептуально, от пользователя скрыты. В [24.19] широко обсуждается это различие и другие связанные с ним вопросы.)
Здесь следует отметить некоторые важные моменты.
Необходимо понимать, что, как будет показано в разделе 24.4, наличие идентификаторов объектов не позволяет полностью исключить применение пользовательских ключей. Точнее, пользовательские ключи необходимы для общения с внешним миром, хотя внутри базы данных все объекты могут ссылаться один на другой только с помощью идентификаторов объектов.
Что является идентификатором производного объекта, например "соединения" некоторого объекта класса ЕМР и соответствующего объекта класса DEPT или "проекции" объекта класса DEPT по атрибутам BUDGET и MGR? Это очень важный вопрос для производных объектов, рассмотрение которого мы отложим до раздела 24.5.
Идентификаторы объектов часто служат предметом критических замечаний, вызванных тем, что объектные системы выглядят, как "модифицированный стандарт CODASYL". Стандарт CODASYL использовался для сетевых систем управления базами данных (например, для СУБД IDMS), которые были созданы до появления реляционного подхода. Использование идентификаторов объектов приводит к низкоуровневому стилю программирования (см. раздел 24.4.), что очень напоминает устаревший стиль программирования согласно стандарту CODASYL. Кроме того, поскольку идентификаторы объектов являются указателями, часто можно услышать, что системы типа CODASYL ближе к объектным системам, чем реляционные, и что реляционные системы основаны на значениях, в то время как объектные системы — на идентичности.
Классы, экземпляры и коллекции
В области объектных систем четко разделяются концепции класса, экземпляра и коллекции. Как уже отмечалось, объектный класс является, в основном, типом данных, причем он может быть встроенным или определенным пользователем, а также быть сколь угодно сложным7. Каждый класс способен принять сообщение NEW, которое приводит к созданию нового (изменяемого) экземпляра объекта данного класса.
Замечание. Вызываемый этим сообщением метод иногда называют конструктором класса.
Ниже приводится пример такого сообщения, записанного с помощью некоторого гипотетического синтаксиса.
Е := ЕМР NEW ( 'Е001', 'Smith', MONEY ( 50000 ), POS ) ;
7
Как уже подчеркивалось в разделе 24.2,
в некоторых системах используются оба
понятия— и "тип", и "класс".
В этих системах "тип" означает
тип,
т.е.
содержание
или
сущность
понятия,
а "класс" означает применение
этого
понятия, т.е. определенную коллекцию,
или
иногда реализацию
данного
типа. В других системах данные термины
используются иначе... Мы же по-прежнему
будем употреблять термин "класс"
для обозначения типа в том смысле, что
и в главе 5.
Поскольку одни объекты могут ссылаться на любые другие объекты с помощью идентификаторов, один объект может совместно использоваться несколькими другими объектами. В частности, один и тот же объект может одновременно относиться к нескольким различным коллекциям объектов. В продолжение рассматриваемого примера приведем еще одно выражение.
CLASS EMP_COLL
PUBLIC ( EMPS REF ( SET ( REF ( EMP ))))... ;
ALL_EMPS := EMP_C0LL NEW ( ) ;
ALL_EMPS ADD ( E ) ; Пояснения
Объект класса EMP_COLL содержит одну открытую переменную экземпляра EMPS, значением которой является указатель (идентификатор) на изменяемый объект, значение которого представляет собой набор указателей на отдельные объекты класса ЕМР.
ALL_EMPS — это программная переменная, значением которой является идентификатор объекта класса EMP_COLL. После выполнения операции присвоения она будет содержать идентификатор объекта, значением которого, в свою очередь, будет идентификатор пустого множества идентификаторов объектов ЕМР.
ADD — это метод объектов класса EMP_C0LL. В рассматриваемом примере данный метод применяется для объекта класса, идентификатор которого содержится в программной переменной ALL_EMPS, и предназначается для добавления идентификатора объекта ЕМР, который содержится в программной переменной Е, к набору идентификаторов (изначально пустому). Причем идентификатор этого набора содержится в объекте EMP_COLL, идентификатор которого находится в программной переменной ALL_EMPS.
Рассмотрев приведенную выше последовательность операций, можно заметить, что переменная ALL_EMPS связана с набором объектов ЕМР, который в текущий момент содержит только один объект, а именно — объект, описывающий сотрудника с номером 'Е001'. (Помимо всего прочего, обратите внимание на то, что необходимо упомянуть значение ключа пользователя в последнем предложении!)
Конечно, в некоторый заданный момент может существовать любое количество разных и, возможно, перекрывающихся "наборов сотрудников", например следующих.
PROGRAMMERS := EMP_COLL NEW ( ) ; PROGRAMMERS ADD ( E ) ;
HIGHLY_PAID := EMP_C0LL NEW ( ) ; HIGHLY_PAID ADD ( E ) ;
Приведенный ниже пример SQL-выражения показывает, что в реляционных системах все может быть организовано совсем иначе.
CREATE TABLE ЕМР ( EMPf ... ,
ENAME ... , SALARY ... , POSITION ...)...;
В этом случае тип и коллекция создаются одновременно, причем сложный тип соответствует заголовку таблицы, а исходно пустая коллекция соответствует содержанию таблицы. Точно так же приведенное ниже SQL-выражение позволяет одновременно создать отдельную строку ЕМР и добавить ее к коллекции ЕМР.
INSERT INTO ЕМР ( ... ) VALUES (...);
Можно сделать вывод, что организация этих действий с помощью языка SQL характеризуется следующими особенностями.
Отдельный "объект" класса ЕМР не может существовать, не являясь частью некоторой "коллекции", фактически — какой-то единственной "коллекции" (подробности приведены ниже).
Не существует непосредственного способа создания двух различных "коллекций" объектов одного и того же "класса" ЕМР (подробности приведены ниже).
Не существует непосредственного способа совместного использования одного и того же "объекта" в нескольких "коллекциях" "объектов" ЕМР (подробности приведены ниже).
Именно такие претензии иногда можно услышать, однако они не выдерживают серьезной критики. Во-первых, для достижения равноценного эффекта в каждом случае может применяться реляционный метод использования внешнего ключа. Например, можно определить две базовые таблицы, PROGRAMMERS (программисты) и HIGHLY_PAID (высокооплачиваемые), каждая из которых состоит из номеров соответствующих сотрудников. Во-вторых, что еще важнее, для достижения того же эффекта может быть применен реляционный метод с использованием представлений. Например, таблицы PROGRAMMERS и HIGHLY_PAID можно определить как представления, созданные на основе базовой таблицы ЕМР.
CREATE VIEW PROGRAMMERS
AS SELECT EMP#, ENAME, SALARY, POSITION FROM EMP
WHERE POSITION = 'Programmer' ;
CREATE VIEW HIGHLY_PAID
AS SELECT EMPi, ENAME, SALARY, POSITION FROM EMP
WHERE SALARY > <некоторое значение, например 75 00Q> ;
Теперь один и тот же "объект" сотрудника можно одновременно разместить в двух или более "коллекциях". Кроме того, участие в коллекциях, которые являются представлениями, управляется системой автоматически, а не программистом вручную.
Завершая эту тему, следует упомянуть об одной интересной параллели, существующей между изменяемыми объектами объектных систем и явно заданными динамическими переменными некоторых языков программирования (например, базовыми переменными языка PL/I). Как и в случае изменяемых объектов данного класса, может существовать любое количество отдельных явных динамических переменных данного типа, память для которых выделяется во время выполнения явно заданными указаниями программиста. Более того, эти отдельные переменные, как и отдельные изменяемые объекты, не имеют имен, а потому на них можно ссылаться только с помощью указателей. Например, в языке PL/I можно записать такую последовательность выражений.
DCL XYZ INTEGER BASED ; /* XYZ - базовая переменная */ DCL Р POINTER ; /* Р - указатель */
ALLOCATE XYZ SET { Р ); /* создание нового экземпляра XYZ, */
/* на который указывает Р */
Р -> XYZ = 3 ; /* присвоение значения 3 экземпляру */
/* XYZ, на который указывает Р */
Этот записанный на языке PL/I код очень похож на рассмотренный ранее объектный код. В частности, объявление базовой переменной подобно объявлению класса объектов, а операция ALLOCATE — созданию нового экземпляра объекта этого класса. Таким образом, основная причина, по которой в объектной модели необходимы идентификаторы, заключается в том, что те объекты, которые они идентифицируют, не обладают уникальными именами (точно так же, как базовые переменные в языке PL/I).
Иерархии классов
Описание концепций объектного подхода было бы неполным без рассмотрения иерархий классов (их не следует путать с иерархиями вложения). Однако объектная концепция "иерархии классов", в сущности, является тем же, что и концепция иерархии типов, рассмотренная в главе 19. Следовательно, здесь можно ограничиться несколькими краткими определениями (большей частью это перефразированные выражения из главы 19) и соответствующими примерами.
Замечание. Напомним, что в объектном мире, как и в остальных случаях, все еще нет полной согласованности относительно концепции абстрактной модели наследования, поэтому различные системы наследования существенно отличаются одна от другой на уровне деталей.
Начнем с того, что объектный класс Y является подклассом класса X, а объектный класс X — суперклассом объектного класса Y тогда и только тогда, когда каждый объект класса Y обязательно является и объектом класса X (т.е. "Y ISA X"). В этом случае объект класса Y наследует переменные экземпляра и методы класса X. Наследование переменных экземпляра обычно называют наследованием структуры, а наследование методов — наследованием поведения. В истинно объектных системах не может быть наследования структуры, а возможно лишь наследование поведения (по крайней мере для скаляров и инкапсулированных объектов), поскольку нет структуры для наследования (т.е. пользователю никакая структура не видна). Однако на практике объектные системы обычно несовершенны и в какой-то мере поддерживают структурное наследование, которое, подчеркиваем, означает наследование открытых переменных экземпляра.
Если класс Y является подклассом класса X, то пользователю предоставляется возможность применять объект класса Y вместо объекта класса X везде, где это допустимо, т.е. в качестве аргумента различных методов. Этот принцип называется принципом подстановки и весьма полезен для повторного использования кода. Однако, поскольку в объектных системах не всегда четко прослеживается разница между значениями и переменными (т.е. между неизменяемыми и изменяемыми объектами), возникают проблемы различения значения и возможного замещения переменной (этот вопрос обсуждается в главе 19). Возможность применять один и тот же метод для объектов класса X и класса Y называется полиморфизмом.
Обычно объектные системы поставляются с определенной встроенной иерархией классов. Например, в системе OPAL (см. раздел 24.4) каждый класс рассматривается как подкласс некоторого уровня встроенного класса OBJECT (поскольку "все является объектами"). Встроенные подклассы класса OBJECT включают классы BOOLEAN, CHAR, INTEGER, COLLECTION и др. Класс COLLECTION, в свою очередь, включает подкласс BAG, а класс BAG содержит класс SET и т.д. и т.п.
Наконец, в некоторых системах, кроме одиночного наследования, в той или иной форме поддерживается множественное наследование. Однако автору не известно ни одной системы, которая поддерживала бы наследование кортежей или отношений (как одиночное, так и множественное) в смысле, который подразумевался в [3.3].