Главная » SQL, Базы данных » ВСЕОБЪЕМЛЮЩИЙ ПРИМЕР объектного подхода

0

В предыдущей главе были представлены базовые концепции объектного подхода. В данной главе на исчерпывающем примере последовательно демонстрируется применение этих идей на практике, а именно: здесь показано, как определяется объектная база данных, как она пополняется данными и как в ней выполняются операции выборки и обновления данных. В  рассматриваемом  примере используются объектная СУБД GemStone (разработка корпорации GemStone Systems) и ее язык запросов OPAL [25.13]. Язык OPAL, в свою очередь, основан на языке Smalltalk [25.23].

Примечание. Язык Smalltalk относится к числу "наиболее ранних и чистых воплощений" объектного подхода, поэтому он используется здесь в качестве  примера, но ради справедливости следует отметить, что в программных продуктах и приложениях он все чаще заменяется языком C++, а в последнее время— языком Java.

В качестве примера воспользуемся упрощенной версией базы данных  профессиональной подготовки из упр. 9.7 главы 9. В этой базе данных содержится информация о схеме подготовки и обучения специалистов внутри некоторой компании. Для каждого

курса обучения (COURSE) в базе данных содержится описание отдельных потоков, организованных для его изучения (OFFERING). Для каждого потока хранятся данные обо всех его слушателях (ENROLLMENT) и преподавателях (TEACHER). Кроме того, в базе содержатся сведения о сотрудниках компании ЕМР. Реляционную версию базы данных можно

описать следующим образом.

COURSE    { COURSE*, TITLE }

OFFERING  { COURSES, OFF#, OFFDATE, LOCATION } TEACHER   { COURSES, OFF#, EMP# }

ENROLLMENT { COURSE*, OFF#, EMP#, GRADE }

EMP                                         { EMP#, ENAME, SALARY, POSITION }

Рис. 25.6. Схема связей для образовательной базы данных

На рис. 25.6 показана схема связей для рассматриваемой базы данных.

Определение данных

Теперь перейдем к определению данных на языке OPAL для образовательной базы данных. Ниже приводится первое определение объектного класса ЕМР,  описывающего сотрудников (для удобства строки этого определения пронумерованы).

1    OBJECT SUBCLASS : ‘ЕМР’

2        INSTVARNAMES : #[ ‘ЕМР#’, ‘ENAME’, ‘POSITION’ ]

3        CONSTRAINTS : #[ #[ #ЕМР#, STRING ] ,

4                                   [ #ENAME, STRING ],

5                                   [ #POSITION, STRING ] ] .

Пояснение. В строке 1 определен объектный класс ЕМР как подкласс  встроенного класса OBJECT. (Согласно терминологии языка OPAL, в строке 1 передается сообщение объекту OBJECT с запросом вызвать метод SUBCLASS; в этом вызове метода заданы фактические параметры INSTVARNAMES и CONSTRAINTS. Для определения нового класса, как и всего прочего, в языке OPAL необходимо отправить сообщение объекту.) В строке 2 указано, что объекты класса ЕМР имеют, соответственно, три закрытые переменные экземпляра — ЕМР#, ENAME и POSITION, а в строках 3-5 на эти переменные экземпляра накладываются ограничения, указывающие, что они должны содержать объекты класса STRING.

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

Подчеркнем, что переменные экземпляра ЕМР#, ENAME И POSITION— закрытые переменные для класса ЕМР, поэтому доступ к ним по именам допустим только в коде реализации методов этого класса. В качестве примера ниже даны определения методов "получить и установить", т.е. методов, позволяющих выбрать и обновить номера служащих (здесь символ " ^" можно читать как "возвратить").

METHOD : ЕМР

GET_EMP#

^ЕМР#

%

METHOD : ЕМР

SET_EMP# : EMP#_PARM

ЕМР# := EMP#_PARM %

В следующем подразделе о методах мы поговорим подробнее. А сейчас рассмотрим определение класса COURSE.

1    OBJECT SUBCLASS : ‘COURSE’

2        INSTVARNAMES : #[ ‘COURSE*’, ‘TITLE’, ‘OFFERINGS’ ]

3        CONSTRAINTS : #[ #[ #COURSE#, STRING ] ,

4                                   [ #TITLE, STRING ] ,

5                                   [ SUFFERINGS, OSET ] ] .

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

1    OBJECT SUBCLASS : ‘OFFERING’

2        INSTVARNAMES : #[ ‘OFF*’, ‘ODATE’, ‘LOCATION’,

3                                             ‘ ENROLLMENTS ‘ , ‘ TEACHERS ‘ ]

4        CONSTRAINTS : #[ #[ #OFF#, STRING ] ,

5                                   [#ODATE, DATETIME ],

6                                   [#LOCATION, STRING ],

7                                   [«ENROLLMENTS, NSET ],

8                                   [#TEACHERS, TSET ] ] .

Пояснение. В строке 7 определяется закрытая переменная экземпляра ENROLLMENTS, содержащая  идентификатор  объекта  класса  NSET.  Говоря  неформально,  переменная ENROLLMENTS обозначает множество всех слушателей  в данном потоке. Аналогичным образом, переменная TEACHERS обозначает множество всех преподавателей рассматриваемого потока. Поэтому здесь вновь  используется представление иерархии вложения. Определения классов NSET и  TSET будут даны ниже. Определение класса слушателей ENROLLMENT может быть записано следующим образом.

1    OBJECT SUBCLASS : ‘ENROLLMENT’

2        INSTVARNAMES : # [ ‘ EMP’ , ‘ GRADE’ ]

3        CONSTRAINTS : #[ #[ #EMP, EMP ] ,

4                                   [ #GRADE, STRING ] ].

Пояснение. В строке 3 определяется закрытая переменная экземпляра ЕМР, содержащая идентификатор объекта класса ЕМР, представляющий отдельного сотрудника, который является слушателем курса.

Примечание. Чтобы продолжить создание иерархии вложения, объект ЕМР помещается  "знутрь"  соответствующего  объекта  ENROLLMENT.  Однако  здесь  можно  заметить асимметрию: зачисление сотрудников на обучение в разные потоки описывается как отношение типа "многие ко многим", но участники  этой связи, сотрудники и потоки, трактуются совершенно по-разному.

Наконец, рассмотрим объекты, представляющие преподавателей. Здесь мы немного отойдем от оригинальной реляционной версии базы данных и будем рассматривать преподавателей (TEACHER) как подкласс класса сотрудников (ЕМР).

1    ЕМР SUBCLASS : ‘TEACHER’

2           INSTVARNAMES  : #[ ‘COURSES’ ]

3           CONSTRAINTS    : #[ #[ #COURSES, CSET ] ] .

Пояснение. В строке 1 определен объектный класс TEACHER, который является подклассом ранее определенного класса ЕМР (иными словами, класс TEACHER  соединен связью ISA с классом ЕМР). Таким образом, каждый отдельный объект TEACHER имеет закрытые переменные экземпляра ЕМР#, ENAME И POSITION (которые унаследованы10 от класса ЕМР), а также переменную COURSES, которая  содержит идентификатор объекта класса CSET. Объект CSET обозначает множество всех курсов, которые может вести данный преподаватель. Каждый объект TEACHER также наследует все методы класса ЕМР.

Как уже отмечалось, в приведенных выше определениях классов предполагалось существование нескольких классов коллекций ESET, CSET, OSET, NSET и TSET. Ниже даются определения всех этих классов, начиная с класса ESET.

1    SET SUBCLASS     : ‘ESET’

2          CONSTRAINTS : ЕМР .

Пояснение. В строке 1 дается определение объектного класса ESET, который является подклассом встроенного класса SET. В строке 2 на объекты класса ESET накладывается ограничение: они должны быть множествами идентификаторов объектов класса ЕМР. В общем случае может существовать произвольное количество объектов класса ESET, но в данной ситуации будет создан только один объект (подробности приводятся в следующем подразделе), который будет  представлять собой множество идентификаторов всех объектов класса ЕМР, которые в настоящее время существуют в базе данных. Выражаясь неформально, этот единственный объект ESET можно рассматривать как объектный аналог базовой переменной отношения ЕМР в реляционной версии базы данных.

Определения классов CSET, OSET, NSET и TSET аналогичны (они приводятся ниже). Однако для каждого из них придется создать не один, а несколько объектов соответствующей коллекции классов. Например, в нашем случае будет существовать столько коллекций объектов OSET, сколько существует отдельных объектов COURSE.

SET SUBCLASS   :     ‘CSET’ CONSTRAINTS :                                        COURSE .

SET SUBCLASS   :     ‘OSET’ CONSTRAINTS :                                        OFFERING .

SET SUBCLASS    :     ‘NSET’ CONSTRAINTS :                                        ENROLLMENT .

SET SUBCLASS    :     ‘TSET’ CONSTRAINTS :TEACHER .

10 Заметим, что здесь наследуется закрытое представление (т.е. физическая реализация).

Заполнение базы данных

Теперь опишем, как можно поместить в рассматриваемую базу данных  требуемую информацию. При этом остановимся на пяти основных классах объектов (EMP, COURSE И т.д.). Начнем с сотрудников. Напомним о нашем намерении собрать вместе идентификаторы всех объектов ЕМР в единственном объекте ESET. Таким образом, прежде всего необходимо создать объект ESET, как показано ниже.

OID_OF_SET_OF_ALL_EMPS    :=   ESET  NEW   .

Выражение  в  правой  части  этого  оператора присваивания  возвращает  объектный идентификатор (OID) нового пустого экземпляра объекта класса ESET (т.е. пустое множество идентификаторов объектов класса ЕМР), а затем идентификатор этого нового экземпляра присваивается программной  переменной  OID_OF_SET_OF_ALL_EMPS. Говоря очень неформально, эта переменная обозначает "множество всех сотрудников".

Теперь каждый раз при создании нового объекта класса ЕМР идентификатор  этого объекта следует помещать в объект ESET, идентификатор которого хранится в переменной OID_OF_SET_OF_ALL_EMPS. Поэтому для создания объекта  класса  ЕМР и вставки его идентификатора в объект класса ESET необходимо определить специальный метод. (Еще один вариант состоит в том, что для выполнения такой же задачи может быть написана прикладная программа.) Код указанного метода приведен ниже.

1 METHOD : ESET                                                                                                                          " анонимный! "

2    ADD_EMP# : EMP#_PARM                                             " формальные параметры "

3    ADD_ENAME : ENAME_PARM

4    ADD_POS  : POS_PARM

5    | EMP_OID |                                                                                                                          " локальная переменная "

6    EMP_OID := EMP NEW .                                                                                " новый сотрудник "

7    EMP_OID SET_EMP#  : EMP#_PARM ;   " инициализация "

8               SET_ENAME : ENAME_PARM ;

9               SET_POS    : POS_PARM .

10  SELF ADD: EMP_OID .                                                                                 " вставка "

11 %

Пояснение

и В строке 1 начинается запись кода данного метода (который завершается символом "%" в строке 11), который применяется к объектам класса ESET. (На самом деле, в системе во время выполнения программы будет существовать один и только один объект класса ESET.)

■    В строках 2-4 определены три параметра с внешними  именами ADD_EMP#, ADD_ENAME и ADD_POS. Эти имена будут использованы в сообщениях, вызывающих данный метод. Соответствующие внутренние имена EMP#_PARM, ENAME_PARM И POS_PARM будут применяться только внутри кода реализации данного метода.

■    В строке 5 определена локальная переменная EMP_OID, а в строке 6 ей присвоен идентификатор нового неинициализированного экземпляра объекта класса ЕМР.

■    В строках 7—9 передается сообщение новому объекту класса ЕМР с указанием трех вызываемых методов (SET_EMP#, SET_ENAME и SET_POS) и передачей одного фактического   параметра   каждому  из   них    (EMP#_PARM  для   SET_EMP#, ЕNАМЕ_РАRМ для SET_ENAME И РОS_РАRМ для SET_POS).

Примечание. Здесь предполагается, что методы SET_ENAME и SET_POS (как и метод SET_EMP#, показанный выше) также должны быть определены заранее.

■     В строке 10 передается сообщение объекту SELF. Это имя объекта является специ альным обозначением, представляющим во время выполнения тот текущий объект, в котором определен указанный метод (т.е. сообщение передается самому текущему целевому объекту). Сообщение вызывает применение встроенного метода ADD к этому объекту (метод ADD предусмотрен во всех классах, определяющих кол лекции). В результате идентификатор объекта, который содержится в локальной переменной EMP_OID, будет вставлен в объект, идентифицируемый значением пе ременной SELF (в данном случае это будет объект ESET, содержащий идентифи каторы всех существующих на текущий момент объектов класса ЕМР). Примечание. Переменная SELF необходима потому, что параметр, соответствую щий объекту-получателю, не имеет собственного имени (см.строку 1).

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

Теперь создан метод для вставки в базу данных новых объектов ЕМР, но до сих пор такая операция еще не была выполнена. Поэтому ниже приведен пример  вставки в базу данных сведений о сотрудниках.

OID_OF_SET_OF_ALL_EMPS ADD_EMP# : ‘E009′ ADD_ENAME : ‘Helms’ ADD_POS   : ‘Janitor’

.

При использовании приведенного выражения будет создан объект класса ЕМР для сотрудника с номером Е009, а идентификатор этого объекта будет добавлен к множеству уже существующих идентификаторов объектов класса ЕМР.

Обратите внимание на то, что встроенный метод NEW никогда не должен использоваться для класса ЕМР, кроме тех случаев, когда он является частью только что определенного метода. Иначе могут быть созданы некоторые объекты класса ЕМР с оборванными связями, которые не будут представлены в объекте ESET, содержащем идентификаторы всех существующих объектов ЕМР.

Примечание. Следует принести извинения за слишком частое повторение таких громоздких выражений, как "только что определенный метод" и "объект ESET, содержащий идентификаторы всех существующих объектов ЕМР", но иначе  нелегко точно описать предметы, не имеющие названий.

Объекты для сотрудников представляют собой наиболее простой случай, поскольку они соответствуют обычным сущностям (согласно терминологии модели типа "сущность/связь") и не содержат никаких других внедренных в них объектов (не считая неизменяемых).

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

1.  Применить метод NEW к классу CSET в целях создания исходно пустого множества всех курсов  (на самом деле —  множества  идентификаторов  объектов  класса COURSE).

2.  Определить метод для создания нового объекта класса COURSE и вставить его идентификатор в множество всех курсов. Этот метод принимает в качестве факти ческих параметров указанные значения COURSE# и TITLE И создает новый объект COURSE с этими заданными значениями. Кроме того, с помощью этого метода к классу OSET применяется метод NEW для создания первоначально пустого множе ства идентификаторов потоков OFFERING, а затем идентификатор этого пустого множества идентификаторов потоков помещается в переменную OFERINGS внут ри нового объекта класса COURSE.

3.  Вызвать только что определенный метод для каждого отдельного курса.

Теперь создадим объекты потоков. Для этого необходимо выполнить перечисленные ниже действия.

1.          Определить метод для создания нового объекта класса OFFERING. Этот метод должен принимать в качестве фактических параметров значения переменных OFF#,  ODATE и  LOCATION и  приводить к созданию нового объекта  класса OFFERING с указанными параметрами. Кроме того, потребуется выполнить неко торые дополнительные действия.

■     Для  создания  исходно  пустого  множества  идентификаторов   слушателей ENROLLMENT следует применить метод NEW к классу NSET, а затем поместить идентификатор    этого    пустого    множества    слушателей    в   переменную ENROLLMENTS внутри нового объекта класса OFFERING.

■     Для создания исходно пустого множества идентификаторов преподавателей TEACHER следует применить метод NEW к классу NSET, а затем поместить иден тификатор этого пустого множества преподавателей в переменную TEACHERS внутри нового объекта класса OFFERING.

2.          Данный метод принимает в качестве фактического параметра значение COURSE*, после чего значение COURSE# используется в нем для выполнения описанных ни же действий.

■     Выполнить поиск11 соответствующего объекта COURSE   для нового объекта OFFERING   (рекомендации по выполнению этого действия приведены в сле дующем подразделе).

"  Безусловно, данный метод должен предотвращать попытки создать новый объект потока, если не может быть найден соответствующий курс. Здесь и в дальнейшем описании такие исключительные  ситуации подробно не рассматриваются.

■     Найти таким образом множество всех потоков для данного объекта класса

COURSE.

■     Добавить идентификатор нового объекта класса OFFERING К соответствующе му множеству всех потоков.

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

Наконец, следует вызвать только что определенный метод для каждого отдельного потока.

Обратите внимание на то, что (в соответствии с используемым представлением иерархии вложения) здесь не было создано множество всех потоков. Одним из следствий этого упущения становится то, что в любом запросе, областью действия которого становится это множество (например: "Определить все потоки,  организованные в Нью-Йорке"), придется использовать определенный объем  процедурного кода, позволяющего исправить эту ситуацию (см. следующий подраздел).

Теперь рассмотрим процедуру создания объектов слушателей. Эти объекты (ENROLLMENT)

отличаются от объектов потоков тем, что содержат переменную экземпляра ЕМР, значение которой является идентификатором соответствующего объекта ЕМР. Поэтому последовательность действий должна быть такой, как описано ниже.

1.         Определить метод для создания нового объекта класса ENROLLMENT. Этот метод в качестве фактических параметров принимает указанные значения COURSE*, OFF*, ЕМР# и GRADE и создает новый объект ENROLLMENT с заданным значением GRADE. Кроме того, требуется выполнить некоторые дополнительные действия.

■     Использовать значения COURSE# и OFF# для поиска соответствующего объекта

OFFERING ДЛЯ НОВОГО объекта ENROLLMENT.

■     Найти множество всех слушателей для данного объекта класса OFFERING.

■     Добавить идентификатор нового объекта класса ENROLLMENT к соответствую щему множеству всех слушателей.

■     Кроме того, потребуется выполнить описанные ниже действия

■     Использовать значение ЕМР*#для поиска соответствующего объекта ЕМР.

■     Поместить идентификатор объекта ЕМР в переменную ЕМР внутри нового объ екта класса ENROLLMENT.

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

Наконец, перейдем к созданию объектов преподавателей. Различие между способами создания объектов для преподавателей и потоков заключается в том, что класс TEACHER является подклассом класса ЕМР. Ниже приведена последовательность действий, которые необходимо выполнить в данном случае.

1.          Определить метод создания нового объекта класса TEACHER. Этот метод принима ет в качестве фактических параметров заданные значения COURSE#, OFF# и ЕМР#. Потребуются также некоторые дополнительные действия.

■    Использовать значение ЕМР# для поиска соответствующего объекта класса ЕМР.

■    Заменить наиболее определенный класс этого объекта ЕМР классом TEACHER, поскольку данный сотрудник теперь является также преподавателем (но способ указанного изменения класса в значительной степени зависит от конкретной рассматриваемой системы, поэтому дополнительные сведения на эту тему здесь не приведены). Кроме того, должны быть выполнены описанные ниже действия.

■    Использовать значения COURSE# и OFF# для поиска соответствующего объекта

OFFERING ДЛЯ НОВОГО объекта TEACHER.

■    Найти множество всех преподавателей для этого объекта OFFERING.

■    Добавить идентификатор нового объекта класса TEACHER к соответствующему

множеству всех преподавателей.

2.          Определить множество всех курсов, которые может вести данный преподаватель, а также задать соответствующим образом значение переменной COURSES в новом объекте класса TEACHER. Но здесь эти подробности не приведены.

3.          Вызывать только что определенный метод для каждого объекта, описывающего отдельного преподавателя.

Операции выборки

Прежде чем приступить к подробному описанию операций выборки, следует отметить (хотя это и вполне очевидно), что язык OPAL, как и другие объектные языки в целом, функционирует по принципу последовательной обработки  отдельных записей (или, по меньшей мере, отдельных объектов), а не их множеств. Поэтому для решения большинства проблем программист вынужден  применять процедурный код. Рассмотрим лишь один пример — запрос: "Определить все потоки для курса с номером С001, которые организованы в  городе New York". Для простоты предположим, что есть переменная OOSOAC,  значение которой является идентификатором множества всех курсов.  Ниже приведен код для такого запроса.

1  | COURSE_C001 , C001_OFFS , C001_NY_OFFS |

2    COURSE_C001

3         := OOSOAC DETECT : [ :CX | ( CX GET_COURSE# ) = ‘C001′ ] .

4    C001_OFFS

5         := COURSE_C001 GET_OFFERINGS .

6    C001_NY_OFFS

7         := C001_OFFS SELECT :

8                        [   :OX   |    (   OX GET_LOCATION  )   =   ‘New York’   ]     .

9  ^  C001_NY_OFFS   .

Пояснение

1.  В строке 1 объявлены три локальные переменные: COURSE_C001 (которая  будет использована  для  хранения  идентификатора  объекта  курса  с  номером  С001), C001_OFFS (которая будет использована для хранения идентификатора объекта

множества всех потоков для курса с номером С001) и C001_NY_OFFS (которая будет использована для хранения идентификатора множества идентификаторов для требуемых потоков, т.е. потоков, организованных в Нью-Йорке).

2.     В строках 2 и 3 передается сообщение объекту (коллекции), обозначенному пере менной OOSOAC.  Это сообщение вызывает применение  встроенного метода DETECT к этой коллекции. Формальным параметром метода DETECT является вы ражение в следующей форме.

[   :х  |    р{х)     ]

Здесь р(х) — логическое выражение, включающее переменную х, а х, по  сути, представляет собой переменную области значений, которая принимает свои значения среди элементов коллекции, к которым применяется метод DETECT (в рассматриваемом примере этот метод применяется к множеству объектов COURSE). В результате выполнения метода DETECT  возвращается идентификатор первого найденного объекта х этого множества, для которого выражение р (х) принимает значение TRUE (в  рассматриваемом примере это — экземпляр объекта класса COURSE для курса с номером С001)12. Затем идентификатор этого объекта класса COURSE присваивается переменной COURSE_C001.

Примечание. Фактически также возможно передать методу DETECT замаскированный формальный параметр, чтобы можно было учесть тот случая, в котором выражение р (х) никогда не принимает значение TRUE.  Но подробные сведения об этом здесь не приведены.

3.      В строках 4 и 5 переменной C001_OFFS присваивается идентификатор множества всех потоков для курса с номером С001.

4.    Строки 6-8 подобны строкам 2 и 3, поскольку встроенный метод SELECT подобен методу DETECT, за исключением того, что он возвращает идентификатор множест ва идентификаторов всех объектов х (а не просто первый обнаруженный из таких объектов), для которых выражение р (х) принимает значение TRUE. В рассматри ваемом примере в результате выполнения этого метода переменной C001_NY_OFFS присваивается идентификатор множества идентификаторов для тех потоков курса с номером С001, которые организованы в городе New York.

5.    В строке 9 этот идентификатор возвращается в точку вызова.

Следует обратить внимание на некоторые перечисленные ниже особенности.

■     Логическое выражение р (х) в методах SELECT и DETECT может содержать (в са мом сложном случае) лишь некоторое количество простых скалярных операторов сравнения, которые соединяются с помощью операторов AND, т.е. сложность ус ловия поиска ограничена.

■     Круглые  скобки,  окружающие  выражение  фактического  параметра   методов SELECT и DETECT, можно заменить фигурными скобками. При использовании фигурных скобок в языке OPAL будет предпринята попытка использовать индекс

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

(если соответствующий индекс существует) в ходе применения данного метода, а при использовании круглых скобок индекс использоваться не будет.

■     Условие, согласно которому метод DETECT возвращает идентификатор первого найденного объекта, для которого значением выражения р (х) является TRUE, оз начает, что найденный объект будет первым найденным при использовании про извольной последовательности поиска, которая будет выбрана в языке OPAL для просмотра множества (поскольку множества не имеет присущих им свойств упо рядочения). В рассматриваемом примере результат не зависит от организации по иска, поскольку первый объект, для которого логическое выражение принимает значение TRUE, фактически является единственным таким объектом.

■     Внимательный читатель непременно заметит широко применяемые выражения наподобие "метод DETECT", хотя, как отмечалось выше, методы в языке OPAL не имеют имен. Действительно, DETECT и SELECT не являются именами методов (а потому выражения наподобие "метод DETECT", строго говоря, является непра вильным). Они, скорее всего, служат именами внешних параметров для некоторых встроенных (и анонимных) методов. Но для краткости и простоты далее в качестве имен методов по-прежнему будут использоваться названия DETECT и SELECT (а также другие подобные им названия для других методов).

■     Кроме того, внимательный читатель заметит, что довольно часто используется вы ражение "метод NEW". В данном случае его не следует считать неправильным — методы, не принимающие иных формальных параметров, кроме обязательных це левых формальных параметров, являются исключением из общего правила в язы ке OPAL, согласно которому методы должны быть анонимными.

Операции обновления

Объектный аналог операции вставки INSERT уже обсуждался в предыдущем подразделе, а объектные аналоги операций обновления UPDATE и удаления DELETE рассматриваются ниже.

■      Обновление. Операции обновления выполняются так же, как операции выборки,

но вместо методов GET_ используются методы SET_.

■     Удаление. Для удаления объектов используется встроенный метод REMOVE. Точнее, он используется для удаления идентификатора указанного объекта из указанной коллекции. Если на данный объект больше не имеется никаких ссылок, т.е. к нему вовсе не может быть осуществлен доступ, то в языке OPAL он автоматически уда ляется системным процессом сбора мусора. Ниже приводится пример реализации операции "удаления сотрудника с номером Е001 из множества всех сотрудников".

Е001  := OID_OF_SET_OF_ALL_EMPS

DETECT : [ : EX | (EX GET_EMP# ) = ‘E001′ ] . OID_OF_SET_OF_ALL_EMPS REMOVE : E001 .

Но как в такой ситуации реализовать правило каскадного удаления ON  DELETE CASCADE? Например, как при удалении некоторого сотрудника  одновременно удалить и сведения обо всех потоках, в которых он проходит обучение? Для этого, естественно, придется создать соответствующую процедуру.

Можно было бы прийти к заключению, что механизм реализации удаления с помощью процесса сбора мусора является всего лишь некоторой  разновидностью реализации правила ограничения удаления ON DELETE  RESTRICT, поскольку объект не удаляется до тех пор, пока на него существует хотя бы одна ссылка. Но в данном случае это не совсем так. Например, объекты потоков (OFFERING) не содержат  идентификаторов  соответствующего  объекта  курса  (COURSE),  поэтому потоки не  накладывают ограничений на удаление объектов курсов. (В иерархиях вложения неявно подразумевается некоторая разновидность правила  каскадного удаления ON DELETE CASCADE, кроме случаев, когда  пользователь выполняет следующее: либо включает идентификатор  родительского объекта в дочерний объект; либо включает  идентификатор  дочернего  объекта в  какой-то  другой объект, хранящийся в базе данных. А в таких ситуациях интерпретация на основе иерархии вложения больше не имеет никакого смысла. В следующем разделе этот вопрос будет рассмотрен при обсуждении обратных переменных.)

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

Источник: Дейт К. Дж., Введение в системы баз данных, 8-е издание.: Пер. с англ. — М.: Издательский дом «Вильямс», 2005. — 1328 с.: ил. — Парал. тит. англ.

По теме:

  • Комментарии