Активные данные
Под “свойством активности данных” понимается механизм, заставляющий оператор SQL производить некоторые действия, потребность в которых в самом операторе явно не выражена. В DB 2 существуют две категории активных данных - ограничения и триггеры. Ограничения являются декларативными утверждениями, истинность которых контролируется системой. Триггеры - это автоматические действия, которые срабатывают каждый раз при возникновении определенного события или условия.
В DB2 поддерживаются следующие виды ограничений : NOT NULLS , UNIQUE , PRIMARY KEY , CHECK , WITH CHECK OPTION , FOREIGN KEY .
Ограничения представляют собой декларативные правила. Триггер выполняет приказы при возникновении определенных событий. Вот некоторые из возможностей механизма триггеров DB 2:
триггер может быть активизирован при выполнении операций занесения, удаления или модификации строк указанной таблицы или при модификации определенных столбцов таблицы;
можно потребовать срабатывания триггера до или после обработки события, которое его активизирует;
триггер может срабатывать в точности один раз при активизации его оператором SQL или же вызываться для каждой строки, изменяемой оператором SQL;
при активизации триггер может вычислять предикат, называемый “условием триггера”; тогда тело триггера выполняется только если его условие истинно;
тело триггера может состоять из одного или нескольких операторов SQL, в которых могут использоваться специальные переменные, указывающие на значения строки или группы строк до и после активизации триггера; если в тело триггера входят операторы модификации базы данных, то авторизация доступа производится от имени создателя триггера, а не того пользователя, оператор которого активизировал триггер.
это конструктор типов, позволяющий производить
Анонимный строчный тип – это конструктор типов, позволяющий производить безымянные типы строк (кортежей). Любой возможный строчный тип получается путем использования ROW . При определении столбца, значения которого должны принадлежать некоторому строчному типу, используется конструкция ROW ( fld 1 , fld 2 , …, fld n) , где каждый элемент fldi , определяющий поле строчного типа, задается в виде тройки fldname , fldtype , fldoptions . Подэлемент fldname задает имя соответствующего поля строчного типа. Подэлемент fldtype специфицирует тип данных этого поля. В качестве типа данных поля строчного типа можно использовать любой допустимый в SQL тип данных, включая другие строчные типы. Необязательный подэлемент fldoptions может задаваться для указания применяемого по умолчанию порядка сортировки, если соответствующий подэлемент fldtype указывает на тип символьных строк, а также должен задаваться, если fldtype указывает на ссылочный тип (см. ниже). Степенью строчного типа называется число его полей.
Дополнительные объектно-реляционные возможности Oracle 9 i
Основные расширения объектно-реляционных возможностей Oracle 8, появившиеся в Oracle 9i , касаются наследования объектных типов и представлений. Эти расширения (в особенности, наследование объектных типов) очень близки к спецификациям SQL :1999.
Объектное представление может определяться в виде подпредставления другого объектного представления с порождением иерархии представлений. При этом множество строк любого наследуемого объектного представления включает все строки всех подпредставлений.
Иерархии представлений обладают следующими дополнительными свойствами:
объектный тип суперпредставления должен являться непосредственным супертипом типа наследуемого представления;
подпредставление наследует объектный идентификатор у своего суперпредставления.
Заметим, что, конечно, механизм наследования представлений, реализованный в Oracle 9i , является гораздо более гибким, чем механизм наследования таблиц в IUS . Понятно также, что при реализации механизма наследования представлений не должны были возникать особые трудности. Но, как кажется автору этой статьи, этот механизм не слишком удобен для использования.
Еще одним новшеством Oracle 9i является возможность определения типов коллекций, тип элементов которых может определяться с использованием других типов коллекций. Примеры соответствующих языковых конструкций слишком громоздки, чтобы приводить их в этой статье.
IBM DB2 Universal Database (UDB)
Компания IBM последней, после Informix и Oracle , объявила свой объектно-реляционный продукт (в конце 1998 г.) и назвала его DB 2 Universal Database (UDB ). Однако, как стало ясно немного позже, базовые идеи объектно-реляционных расширений были заложены еще в продукте компании IBM DB 2 for Common Servers , выпущенном в 1995 г. Эти идеи описаны в замечательной статье Дона Чемберлина [11], и мы начнем с очень изложения этой статьи. После этого мы также кратко обсудим дополнительные объектно-реляционные возможности DB 2, появившиеся после выпуска UDB .
Индивидуальные типы
Индивидуальным типом называется UDT , основанный на единственном встроенном типе (например, INTEGER ). Значения такого типа нельзя прямо использовать в операциях соответствующего базового типа, однако допускается явное приведение значений индивидуального типа к базовому типу. Поясним это на примере.
Пусть заданы следующие определения индивидуальных типов:
CREATE TYPE EMP_NO AS INTEGER FINAL;
CREATE TYPE DEPT_NO AS INTEGER FINAL;
CREATE TYPE PRO_NO AS INTEGER FINAL;
Тогда таблицу EMP можно определить следующим образом:
CREATE TABLE EMP (
EMP_ID EMP_NO,
EMP_NAME VARCHAR(20),
DEPT_ID DEPT_NO,
PRO_ID PRO_NO ) ;
Такое определение таблицы, приведет к тому, что хотя все три индивидуальных типа определены на одном и том же базовом типе INTEGER , попытка выполнить запрос
SELECT EMP_NAME
FROM EMP
WHERE EMP_ID > DEPT_ID ;
будет отвергнута системой (и это правильно, поскольку, скорее всего, запрос задан по ошибке). Но если действительно требуется сравнивать идентификаторы служащих с идентификаторами их отделов, то можно воспользоваться конструкцией явного приведения типа:
SELECT EMP_NAME
FROM EMP
WHERE CAST(EMP_ID TO INTEGER) > CAST(DEPT_ID TO INTEGER) ;
У читателей могут возникнуть законный вопрос: что означает ключевое слово FINAL в приведенных примерах определения индивидуальных типов?
Ответ может быть довольно неожиданным. С формальной точки зрения индивидуальный тип данных является частным случаем структурного типа данных. Обе разновидности UDT определяются единым синтаксисом. В частности, ключевое слово FINAL играет важную роль в определении структурного типа, указывая тот факт, что этот тип может быть использован только для создания объектов, а не для порождения новых типов на основе механизма наследования. При определении индивидуальных типов механизм наследования не используется и поэтому в определении любого индивидуального типа должно присутствовать ключевое слово FINAL .73 Далее, поскольку индивидуальный тип является частным типом структурного типа, для индивидуального типа можно определять методы.
В книгах Джима Мелтона [12-13] неоднократно подчеркивается семантическое сходство понятий индивидуального типа данных и домена в смысле SQL . Более того, утверждается, что в следующих версиях стандарта SQL использование доменов будет сначала объявлено нежелательным, а потом и вовсе будет запрещено. По мнению автора этой статьи, это сделать совсем непросто. Напомним, что в случае использования SQL -домена:
(a) в определении домена указывается базовый встроенный тип данных и, возможно, ограничение допустимых значений, которое распространяется на любой столбец, определенный на данном домене;
(b) для значений столбца, определенного на домене, допускаются все операции, допустимые для базового типа.
Естественно, эти возможности могут использоваться текущими пользователями стандарта SQL . В то же время, в случае использования индивидуального типа данных:
(a) в определении индивидуального типа указывается только базовый тип данных; если столбец определяется на индивидуальном типе данных, то для него обязательно придется специфицировать собственное ограничение целостности;
(b) для значений столбца, определенного на индивидуальном типе данных, не допускаются операции соответствующего базового типа (если не использовать операцию явного приведения типов).
Здесь явно имеются противоречия, для сглаживания которых требуется модифицировать понятие индивидуального типа данных.
Informix Universal Server (IUS)
Informix Universal Server (IUS ) представлял собой реализацию объектно-ориентированной технологии на основе встраивания механизма абстрактных типов данных и механизма наследования в популярный и надежный сервер реляционных баз данных Informix Dynamic Server .78
Интеллектуальные большие объекты
Интеллектуальные большие объекты (smart large objects ), поддерживаемые в IUS , позволяют снять неприятные реализационные ограничения, характерные для трактовки больших объектов (BLOB или CLOB ) реляционными СУБД78. Такие объекты могут подвергаться журнализации и откату, что важно для сохранения целостности и доступности данных.
В IUS -SQL операторы работают не с самими большими объектами, а с их описателями80. Эти описатели помещаются в столбцы таблиц, передаются подпрограммам, написанным с использованием встроенного SQL и т.д. Прикладная программа, получив описатель интеллектуального большого объекта, может работать с ним примерно так же, как и с файлом операционной системы. В частности, программисту, пишущему на ESQL /C (варианту языка C со встроенным SQL , поддерживаемому в Informix ), доступны следующие функции:
ifx_lo_read – чтение;
ifx_lo_readwithseek – чтение с предварительным позиционированием;
ifx_lo_write – запись;
ifx_lo_writewithseek – запись с предварительным позиционированием);
ifx_lo_seek – позиционирование и т.д.81
Использование ссылочных типов
В Oracle 8 строки объектных таблиц называются строчными объектами ( row objects ), а столбцы этих строк –
столбцевыми объектами ( column objects ). Для всех строчных объектов обеспечивается возможность уникальной идентификации. Используется понятие объектного идентификатора, и столбец любой таблицы может быть определен на встроенном типе REF. Значения этого столбца являются своего рода указателями на строчные объекты той же самой или другой объектной таблицы. Считается, что REF - значение, указывающее на некоторый строчный объект, и сам этот строчный объект имеют разные, хотя и связные типы данных. Как утверждает Oracle , запросы с путевыми выражениями, основанными на наличии столбцов ссылочного типа, выполняются быстрее, чем эквивалентные запросы с соединениями.
Как появились ОРСУБД?
Два весьма известных специалиста в области технологии баз данных – Майкл Стоунбрейкер и Вон Ким – оспаривают пальму первенства в направлении ОРСУБД. Стоунбрейкер начал работать в области баз данных в начале 70-х гг. прошлого века в университете Беркли. Его первым всемирно известным проектом была СУБД Ingres , которая существует и используется до сих пор в двух ипостасях – как свободно распространяемая система (университетская Ingres ; код поддерживается в Беркли) и как коммерческая СУБД, принадлежащая компании Computer Associates . В исходном варианте СУБД Ingres отсутствовала поддержка языка SQL (поддерживался собственный язык запросов QUEL ), но система уже обладала некоторыми уникальными чертами, которые, с некоторой натяжкой, можно было бы назвать объектными (например, в СУБД Ingres допускалось определение пользовательских процедур, выполняемых на стороне сервера). Кроме того, в проекте Ingres очень большое внимание уделялось управлению правилами.
В 80-е годы Майкл Стоунбрейкер возглавлял проект Postgres (вариант этой системы под названием PostgreSQL до сих пор является весьма популярным свободно доступным продуктов). В Postgres были реализованы многие интересные средства: поддерживалась темпоральная модель хранения и доступа к данным, и в связи с этим был абсолютно пересмотрен механизм журнализации изменений, откатов транзакций и восстановления БД после сбоев; обеспечивался мощный механизм ограничений целостности; поддерживались ненормализованные отношения (работа в этом направлении началась еще в среде Ingres), хотя и довольно странным способом: в поле отношения может храниться динамически выполняемый запрос к БД.
Одно свойство системы Postgres сближало ее со свойствами объектно-ориентированных СУБД. В Postgres допускалось хранение в полях отношений данных абстрактных, определяемых пользователями типов. Это обеспечивало возможность внедрения поведенческого аспекта в БД, т.е. решало ту же задачу, что и ООСУБД, хотя, конечно, семантические возможности модели данных Postgres были существенно слабее, чем у объектно-ориентированных моделей данных.
Основная разница состояла в том, что в Postgres не предполагалось наличие языка программирования, одинаково понимаемого как внешней системой программирования, так и системой управления базами данных. Как и в Ingres , в исходном варианте Postgres не поддерживался язык SQL (имелся собственный язык запросов Postquel ). Кстати, во времена Postgres Майкл Стоунбрейкер не использовал термин объектно-реляционная система, предпочитая называть свою СУБД системой следующего поколения.
В 90-е гг. Стоунбрейкер создал компанию Illustra , основной целью которой был выпуск коммерческого варианта СУБД Postgress , получившего название Illustra . В этой системе поддерживались основные идеи Postgres , но уже присутствовала и поддержка языка SQL . В конце 1995 г. компания Illustra была поглощена компанией Informix , и это привело к выпуску в 1996 г. СУБД Informix Universal Server .
Имя Вона Кима стало широко известно во второй половине 70-х гг., когда он примкнул к участию в экспериментальном проекте компании IBM System R . Наиболее известная ранняя работа доктора Кима была посвящена преобразованию SQL -запросов с целью превращения запросов с вложенными подзапросами в запросы с соединениями [29].
В 80-е гг. Вон Ким работал в компании MCC , где успешно выполнил реализацию серии прототипов ООСУБД Orion [30]. В этих прототипах были опробованы многие идеи объектно-ориентированных СУБД, которые обсуждались нами в разделе 2. Одной из интересных особенностей проекта было то, что в качестве основного языка программирования использовался объектный вариант известного функционального языка Lisp .
В конце 80-х д-р Ким основал компанию UniSQL , выпустившую в 1991 г. первую версию продукта UniSQL , которую Вон Ким стал называть объектно-реляционной системой. Трудно оценивать коммерческий успех этой СУБД. В настоящее время она принадлежит Корейской национальной телекоммуникационной компании и, по всей видимости, продолжает использоваться. Поскольку UniSQL была первой СУБД, официально называемой объектно-реляционной системой, приведем ее краткое описание.
UniSQL обеспечивает возможность построения так называемых федеративных систем баз данных. При этом предоставляется единое представление данных, которые могут храниться либо в базе данных, непосредственно управляемой UniSQL , либо в какой-либо из реляционных баз данных, управляемой СУБД Oracle , Informix , Sybase и т.д., либо в какой-либо дореляционной базе данных. Сервер UniSQL обеспечивает интегрированный доступ к данным, управляемым разными СУБД.
Разработчики UniSQL полагали, что построение полнофункциональной СУБД, основанной на принципиально новой модели данных, крайне проблематично. Был выбран подход к расширению реляционной модели, выражающийся в следующих четырех принципах:
значениями атрибутов отношений могут быть не только литеральные значения, но и объекты;
значения атрибутов отношений не обязательно являются атомарными;
при построении таблиц (классов) может использоваться механизм наследования;
классы включают операции.
В созданной компанией системе поддерживалось расширение стандарта SQL – SQL /X , одновременно включающее и объектно-ориентированные, и реляционные возможности. В частности, в отличие от подхода, принятого в стандарте ODMG , в одном языке поддерживались возможности и определения данных, и манипулирования ими. В качестве языковых средств программирования приложений поддерживались языки C ++ и Smalltalk .
После этого небольшого исторического очерка перейдем к рассмотрению особенностей трех ведущих СУБД, которые претендуют на поддержку объектно-реляционного подхода, – IBM Informix , Oracle и IBM DB 2. С точки зрения автора данной статьи, этот порядок изложения является справедливым, поскольку соответствует хронологии появления систем на рынке. При описании подходов к организации объектных расширений мы будем стремиться к изложению основных концепций, а не технических деталей. Кроме того, мы не будем стремиться к точному описанию современного состояния систем, поскольку, как отмечалось ранее, в настоящее время компании IBM и Oracle не слишком заинтересованы в развитии объектно-реляционных свойств своих систем, и в этом отношении современные продукты не слишком отличаются от вариантов пяти-шестилетней давности.
Конструируемые типы данных
Важность обеспечения конструируемых типов данных отмечалась и в Первом, и во Втором манифестах. В SQL :1999 обеспечиваются соответствующие (хотя и ограниченные) возможности.
Манифест систем баз данных следующего поколения и его последствия
Через год после публикации Манифеста систем объектно-ориентированных баз данных вышел в свет Манифест систем баз данных следующего поколения [2], инициатором которого, очевидно, был Майкл Стоунбрейкер (хотя у документа формально много авторов). Мы говорим об этом достаточно определенно, поскольку в этом манифесте повсюду видны идеи Стоунбрейкера, использованные им в проектах Ingres и Postgres .
В некотором роде Второй манифест стал ответом миру объектно-ориентированных баз данных со стороны мира SQL -ориентированных баз данных. Если обсуждавшийся в предыдущем разделе Первый манифест носил хотя и немного путанный, но все-таки научный характер, то Второй манифест является в большей степени инженерно-публицистическим документом. В некотором роде это реакция индустрии СУБД на неприятные для нее измышления из мира науки.
Второй манифест (или, вернее, работы, приведшие к его появлению) имел важные последствия. В 1995 г. компания Informix (ныне входящая в состав IBM ) купила компанию Майкла Стоунбрейкера Illustra 52, и Стоунбрейкер стал техническим директором Informix . В начале 1996 г. компания Informix объявила о выпуске принципиально нового продукта Informix Universal Server , в котором, как утверждала компания, сочетались лучшие черты Informix Online Server с развитыми объектными чертами, присущими Illustra .
К выпуску Informix Universal Server очень ревниво отнеслась компания Oracle , которая немедленно заявила, что у нее готов собственный объектно-реляционный продукт, по всем параметрам превосходящий систему компании Informix . Эта система, получившая название Oracle 8, была выпущена в конце лета 1996 г.
Годом позже группе производителей объектно-реляционных СУБД примкнула компания IBM , выпустившая продукт DB 2 Universal Database . (Как выяснилось позже – см., например, [11] – все наиболее важные свойства этого продукта были реализованы еще в 1995 г. в СУБД DB 2 for Common Servers . Просто компания IBM предпочла до поры не афишировать свои расширения.)
Первые пару лет вокруг объектно-реляционных СУБД стоял большой шум.
Позже выяснилось, что маркетинговые ожидания компаний-гигантов оказались преувеличенными. (В частности, это было одной из основных причин падения компании Informix .) Сегодня объектные расширения SQL -ориентированных СУБД предлагаются пользователям лишь в качестве дополнительных, хотя и важных возможностей.
Объектные расширения языка SQL были зафиксированы в стандарте SQL :1999. В той или иной мере эти расширения поддерживаются во всех трех перечисленных выше продуктах. В настоящее время ближе всех к стандарту находятся продукты компании Oracle .
В этом разделе мы сначала приведем изложение (с комментариями) Второго манифеста. Затем мы кратко обсудим основные идеи SQL :1999, относящиеся к объектным расширениям. Наконец, в третьем подразделе будут описаны наиболее интересные черты трех ведущих объектно-реляционных систем.
Наследование типов и таблиц
В IUS механизм наследования может применяться к типам записей и таблицам. Поддерживается только одиночное наследование. Все функции, определенные для супертипа, автоматически распространяются на все его подтипы. В то же время для подтипов могут определяться свои функции, как новые, дополняющие функциональность, так и модифицированные, изменяющие функциональность, унаследованную от предшественника. В последнем случае имеет место перекрытие функций. Значения подтипов могут использоваться почти везде, где разрешено употребление значений их супертипов. Единственное (и вполне естественное) ограничение возникает при отведении памяти и хранении значений. Здесь соответствие типов должно быть точным. Например, если предположить, что тип programmer является подтипом типа employee , и столбец таблицы имеет тип employee , то храниться в нем могут только значения данного типа, но не значения типа programmer .
Наследование таблиц является развитием концепции наследования типов. В иерархии наследования могут участвовать только типизированные таблицы, типы которых (типы записи) образуют параллельную иерархию. Однако, кроме столбцов супертаблиц, подтаблицы наследуют ограничения целостности (первичные ключи, уникальность, ссылочные ограничения), опции хранения, триггеры, индексы и методы доступа.
Отношение наследования между таблицами является динамическим в том смысле, что, если меняются наследуемые характеристики супертаблиц, то это немедленно отражается и на подтаблицах (как на прямых наследниках, так и отделенных несколькими уровнями иерархии). По понятным причинам определения столбцов наследуемых таблиц изменять нельзя, но ограничения, индексы и триггеры – можно.
В IUS операции SELECT , UPDATE и DELETE , примененные к супертаблице, распространяются также и на все ее подтаблицы. Если требуется ограничить запрос ровно одной таблицей, следует употребить конструкцию ONLY . Идеология включения подтаблиц в супертаблицы распространяется и на построение представлений.
Объектная инфраструктура
Истинная объектно-реляционная система должна обеспечивать специальные средства для повышения эффективности приложений, связанных с большими объектами, и минимизации их влияния на системные ресурсы.
В DB 2 поддерживаются три типа данных для хранения больших объектов: BLOB для бинарных объектов, CLOB для символьных строк и DBCLOB для строк, в которых используются двухбайтовые наборы символов. Когда большие объекты сохраняется в столбце таблицы, то на самом деле столбец содержит “дескриптор” каждого такого значения; сами же большие объекты хранятся вне таблицы.
Подсистема восстановления DB 2 дает возможность создателю таблицу выключать обычную журнализацию изменений столбцов с большими объектами. При выключенной журнализации по отношению к таким столбцам гарантируется согласованность транзакций, но столбец не может участвовать в процедуре прямого восстановления.
В среде DB 2 прикладная программа может объявить переменную-“локатор”, которая представляет значение большого объекта, но реально его не содержит. Локатор может быть использован для представления значения большого объекта в любом выражении SQL , и операции над локаторами очень эффективны, поскольку при их выполнении происходит работа с “предписаниями” по материализации, а не с сами значениями больших объектов. При использовании локаторов прикладная программа может выполнить серию действий над значением большого объекта, откладывая его материализацию до последнего момента.
DB 2 дает возможность прикладным программам обмениваться значениями больших объектов между базой данных и файлом без перемещения значений через буфера программы. В программе может быть объявлена переменная “ссылка на файл”, которая содержит имя нужного файла. Ссылка на файл может использоваться в операторах SQL как входная или выходная переменная, представляющая содержимое файла, которое интерпретируется как большой объект. Совместно локаторы и ссылки на файл часто дают возможность обработки больших объектов без их реального считывания в память программы.
Объектная модель SQL
Объектная модель SQL 69 не является тождественной объектным моделям какого-либо объектно-ориентированного языка программирования или какой-либо объектно-ориентрованной системы баз данных (включая модель ODMG – см. разд. 2). Однако при определении объектной модели SQL участники процесса стандартизации тщательно проанализировали ряд других языков и систем с целью выяснения достоинств и недостатков их объектных моделей70.
По мнению авторов стандарта SQL :1999, выработанная ими объектная модель похожа на объектную модель языка Java , но при этом адаптирована к природе языка SQL как языка СУБД с наличием стабильно хранимых метаданных и данных 71.
Объектная модель SQL :1999 включает два основных отличительных компонента – структурные, определяемые пользователями типы данных (User Defined Type – UDT )и типизированные таблицы (Typed Table ). Первый компонент позволяет определять новые типы данных, которые могут быть гораздо более сложными, чем встроенные типы данных языка SQL . При определении структурного UDT требуется специфицировать не только содержащиеся в нем элементы данных, но и семантику типа данных, т.е. его поведение на основе интерфейса вызовов методов. Второй компонент – типизированные таблицы – позволяет определять таблицы, строки которых являются экземплярами (или значениями) UDT , с которым явно ассоциируется таблица.
В стандарте SQL :1999 определены два пакета объектных свойств – минимальный (PKG 006) и полный (PKG 007), которым должны удовлетворять SQL -ориентированные ОРСУБД, претендующие на соответствие стандарту. Ниже мы перечислим свойства, включенные в каждый из пакетов, но смысл этих свойств будет понятен только на основе последующих подразделов.
Пакет PKG 006 включает всего пять свойств:
свойство S 023 (“Basic structured types ”) – возможность определять UDT и их методы с ограниченными возможностями;
свойство S 041 (“Basic reference types ”) – возможность определять и использовать ссылки на экземпляры UDT , входящие в типизированные таблицы;
свойство S 051 (“Create table of type ”) – возможность создания типизированных таблиц;
свойство S 151 (“Type predicate ”) – возможность определения точного типа ( в иерархии типов) экземпляра UDT ;
свойство Т041 (“Basic LOB data type support ”)– возможность определения LOB -типов в смысле SQL (с необязательной поддержкой операций, кроме операций сохранения и полной выборки).
Пакет PKG 007 содержит девять дополнительных свойств:
свойство S 024 (“Enhanced structured types ”) – добавляет к свойству S 023 ряд развитых возможностей, в число которых входят возможности кодирования методов на языках, отличных от SQL , сравнения экземпляров UDT и передача экземпляров UDT в качестве параметров различных процедур;
свойство S 043 (“Enhanced reference types ”) – расширяет свойство S 041 возможностями определения ссылок с областью действия, автоматической проверки законности ссылок и т.д.;
свойство S071 (“SQL-paths in function and type name resolution”) – позволяет использовать путевые выражения SQL (SQL-path) в алгоритме разрешения типа;
свойство S 081 (“Subtables ”) – расширяет возможности свойства S 051, допуская организацию иерархии таблиц, аналогичной иерархии типов соответствующих UDT ;
свойство S 111 (“ONLY in query expressions ”) –обеспечивает возможность выборки только экземпляров указанного типа, без экземпляров любого из его подтипов;
свойство S 161 (“Subtype treatment ”) – дает возможность информировать среду SQL о том, что некоторый экземпляр UDT в действительности является экземпляром указанного подтипа;
свойство S 211 (“User -defined cast functions ”) – разрешает определять подпрограммы, преобразующие экземпляры UDT к другим типам;
свойство S 231 (“Structured type locators ”) – способствует доступу к экземплярам UDT из прикладных программ;
свойство S 023 (“Transform functions ”) – позволяет определять подпрограммы, преобразующие значения UDT в значения предопределенных типов данных и наоборот.
Объектно-реляционные СУБД
В этом разделе мы кратко обсудим, каким образом объектные расширения реализованы в трех ведущих РСУБД – Oracle , IBM Informix и DB 2. Заметим, что компания Microsoft решила не внедрять объектные расширения в свой основной продукт управления базами данных – Microsoft SQL Server . Аналогичное замечание относится и к основному продукту компании Sybase .
Но в начале раздела мы приведем небольшой исторический очерк объектно-реляционного подхода к организации СУБД. Этот очерк носит очень субъективный характер и отражает исключительно личную точку зрения автора этой статьи.
Объектные представления
Объектные представления – это виртуальные таблицы, которые могут обладать структурой и поведением, отличным от структуры и поведения базовых таблиц, лежащих в основе этих представлений. Как и в случае типизированных таблиц, определение объектного представления основывается на определении структурного типа. Объектные представления можно использовать для ограничения доступа к подмножеству строк иерархии таблиц или для сокрытия некоторых столбцов этой иерархии.
Если представление основывается только на выборке строк или таблиц, то определение представления может основываться на уже существующих определениях структурных типов. Однако, если в представлении требуется изменить набор столбцов или поведение базовых таблиц, то в качестве основы иерархии представлений необходимо определить новую иерархию типов.
В этом разделе мы кратко
В этом разделе мы кратко изложим существо объектных расширений, которые включены в стандарт SQL :1999. В этом изложении мы основываемся не на официальном тексте стандарта (он очень формален и скучен), а на книге Джима Мелтона [12], которая, по сути, является неформальным описанием семантики (rationale ) соответствующей части языка. В указанной книге объектным расширениям языка SQL посвящено более 200 страниц. Естественно, наше изложение будет несравненно более кратким (в частности, за счет отказа от приведения синтаксических правил).
Объектные типы и объектные таблицы
Объектные типы в Oracle8 являются аналогом типа записи в IUS. Как и в IUS , для доступа к отдельным полям значений объектного типа используется “точечная” нотация.
В Oracle 8 i при определении объектного типа можно, помимо спецификации структуры значений этого типа, определить и набор методов данного типа. Методы представляют собой функции или процедуры, написанные на PL/SQL, Java, C или другом языке89 и сохранённые в БД или вне её (при наличии регистрации в БД).
Любой метод объектного типа попадает в одну из трёх категорий:
методы-члены
статические методы
методы сравнения.
Методы-члены вызываются в нотации
имя_объекта.имя_метода ( список_параметров )
имеют неявный параметр SELF и могут обращаться к значениям атрибутов объекта90.
Статические методы вызываются в нотации
имя_объектного_типа.имя_метода ( список_параметров )
и не могут обращаться к значениям атрибутов конкретных объектов.
Методы сравненияслужат для сравнения экземпляров объектов. Сравнение объектов может производиться с помощью методов вида MAP или вида ORDER. Метод типа MAP принимает в качестве параметра объект некоторого объектного типа, а возвращает значение одного из встроенных типов, которое может использоваться в операциях сравнения и сортировки. Таким образом, этот метод выполняет отображение объекта
на значение одного из встроенных типов.
Метод типа ORDER сравнивает два объекта и возвращает –1, если первый объект
меньше второго, 0, если объекты равны, и 1, если первый объект больше второго.
Если при определении объектного типа метод сравнения не задан, то объекты этого типа можно сравнивать только на равенство/неравенство, причём объекты не должны содержать элементов тип LOB. Тогда объекты считаются считаться равными, в том и только в том случае, когда все их элементы не содержат неопределенных значений, и значения соответствующих элементов совпадают.
Каждый объектный тип имеет определяемый системой метод-конструктор, который
создаёт новый объект этого типа и присваивает значения его атрибутам.
Метод-конструктор – это функция, которая возвращает объект данного типа. Имя метода-конструктора совпадает с именем объектного типа, имена и типы параметров
конструктора – с именами и типами атрибутов объектного типа.
Объектной таблицей в Oracle 8 называется таблица, строки которой имеют объектный тип. В Oracle 8 не поддерживалось наследование (ни типов, ни таблиц), но уже в Oracle 8 i появилась возможность наследования таблиц почти в той же форме, как это делалось в IUS , но без поддержки параллельной иерархии наследования объектных типов 91.
К объектным представлениям можно обращаться так же, как и к объектным таблицам (по крайней мере, по выборке данных). Можно определять объектные представления на основе других представлений (возможно, объектных).
Определение новых базовых типов данных
IUS позволяет вводить новые базовые типы данных. При этом можно использовать как встроенные в IUS методы доступа и хранения, так и определять новые. Для начала рассмотрим способ создания новых базовых типов с использованием встроенных механизмов хранения.
Необходимость в создании новых базовых типов может возникать во многих случаях. Одним из самых простых случаев - это использование разных метрических систем для одного и того же понятия. Например, если некоторая фирма закупает детали в Америке, то их размеры будут указаны в футах, а цена в долларах. Если аналогичные детали закупаются в Германии, то их размеры указываются в метрической системе, а цена в евро.
IUS позволяет построить новый базовый тип данных, основанный на существующем типе, но обеспечивающий автоматическое преобразование к нужному значению. Сами типы вводятся следующими операторами:
CREATE DISTINCT TYPE usd AS MONEY;
CREATE DISTINCT TYPE euro AS MONEY;
Далее требуется ввести функции преобразования значений из долларов в евро и наоборот, а также описать возможность такого преобразования:
CREATE FUNCTION usd_to_euro (v usd) RETURNS euro; . . .
CREATE FUNCTION euro_to_usd (v euro) RETURNS usd; . . .
CREATE IMPLICIT CAST (usd AS euro WITH usd_to_euro);
CREATE IMPLICIT CAST (euro AS usd WITH euro_to_usd);
После этого можно сравнивать значения типов usd и euro , полученные из разных таблиц, не вызывая явно функцию преобразования. Такое решение существенно снижает возможность внесения ошибок, связанных с преобразованием значений.82
Другой причиной, по которой может возникнуть необходимость во введении нового базового типа данных – это принципиальное отсутствие такого типа. Для этого поддерживается механизм определения типов со скрытой структурой (Opague Types ). Типы со скрытой структурой являются абстрактными в строгом смысле этого слова. IUS лишен какой-либо информации о внутреннем устройстве этих типов и может манипулировать соответствующими значениями только посредством предоставленных разработчиком функций.
Чтобы определить тип со скрытой структурой, необходимо выполнить следующую последовательность действий:
описать на языке C (или другом внешнем языке) структуру определяемых объектов;
написать на языке C (или другом внешнем языке) вспомогательные функции, вызываемые сервером СУБД;
зарегистрировать определяемый тип в базе данных посредством оператора CREATE OPAQUE TYPE;
зарегистрировать вспомогательные функции посредством операторов CREATE FUNCTION и CREATE CAST;
предоставить права доступа к определяемому типу и его вспомогательным функциям посредством оператора GRANT;
написать требующиеся для приложения дополнительные функции, которые можно вызывать средствами SQL, и зарегистрировать их;
если нужно, реализовать специфические для определяемого типа вторичные методы доступа (функции для работы с индексами).
Определение структурных типов
Имя определяемого пользователем типа данных имеет, в общем случае, традиционную для SQL трехзвенную архитектуру – имя_каталога.имя_схемы.имя_типа . Определение структурного UDT может содержать раздел подтипизации. Если этот раздел присутствует в определении UDT , то в нем указывается имя ранее определенного UDT , атрибуты и методы которого будут наследоваться определяемым структурным типом.
Структурные типы, определяемые без использования наследования, называются максимальными супертипами (поскольку у любого из таких типов супертип отсутствует).74 В определениях максимального структурного супертипа или индивидуального типа обязан присутствовать раздел представления. В этом разделе представления может указываться имя предопределенного встроенного типа, и это означает, что определяется индивидуальный тип. Указание списка определений атрибутов соответствует определению структурного типа.
Заметим, что раздел представления может отсутствовать. В этом случае должен присутствовать раздел подтипизации, и представление заново определяемого структурного типа полностью наследуется из определения структурного UDT , имя которого указано в разделе подтипизации.
Имя определяемого атрибута должно отличаться от имен всех других атрибутов определяемого типа, включая имена атрибутов, наследуемых от супертипа, и имена атрибутов типа данных определяемого атрибута. Тип данных может быть любым допустимым в SQL типом данных (включая конструируемые типы ARRAY и ROW и UDT ), кроме определяемого структурного типа и его супертипов.
Для атрибута можно объявить значение по умолчанию. Если типом данных атрибута является встроенный тип данных, то значение атрибута объявляется в том же синтаксисе, что и значение столбца по умолчанию в определении таблицы. Если типом данных атрибута является UDT (индивидуальный или структурный), тип ROW или ссылочный тип (см. следующий подраздел), то единственным допустимым значением по умолчанию является неопределенное значение (NULL ). Если же типом данных атрибута является тип ARRAY , то значением по умолчанию может быть NULL или пустое значение-массив (указывается как ARRAY [] ).
Для каждого определения атрибута, в котором типом атрибута является структурный тип, система автоматически генерирует пару методов, имена которых совпадают с именем атрибута. Первый метод является наблюдателем (observer ). Он вызывается без явных параметров и выдает значение указанного атрибута в значении того структурного типа, к которому применяется. Второй метод является мутатором (mutator ). Он вызывается с одним явным параметром – значением типа аргумента, применяется к некоторому местоположению (столбцу, переменной или параметру), где находится значение определяемого структурного типа, и этот вызов приводит к тому, что значение заменяется новым значением того же типа с измененным соответствующим образом значением данного аргумента.
Присутствие в определении атрибута раздела проверки области действия ссылочных значенийвозможно (и требуется) в том и только в том случае, когда типом определяемого атрибута является ссылочный тип. Более подробно мы обсудим суть этой спецификации в следующем подразделе. Пока лишь кратко заметим, что этот раздел указывает системе, должна ли она проверять, что каждое значение этого атрибута является ссылкой на существующий экземпляр указанного структурного типа, и должна ли система вызывать ссылочное действие при удалении экземпляра, на который ведет ссылка.75
Можно определить инстанциируемый (instantiable ) или неинстанциируемый (not instantiable ) структурный тип. Для неистанциируемого типа не определяется конструктор, и поэтому невозможно создать значение этого типа.76 Поэтому такие типы применимы только для определения инстанциируемых подтипов. Назначение неинстанциируемых типов состоит в моделировании абстрактных концепций, на которых основываются более конкретные концепции. Неинстанциируемые типы могут быть типами атрибутов других структурных типов, типами столбцов, переменных и т.д. Однако в соответствующих местоположениях всегда должно находиться либо значение инстанциируемого подтипа данного неинстанциируемого типа, либо неопределенное значение.
Обязательный раздел окончательности определения указывает на возможность или невозможность определения подтипов определяемого структурного типа. При определении индивидуального типа всегда требуется указывать FINAL . При определении структурного типа в SQL :1999 требуется указание NOT FINAL . Это требование не обосновано, и в следующих версиях стандарта SQL будет разрешено определять структурные типы, от которых невозможно наследование.
Хотя типизированные таблицы обсуждаются в следующем подразделе, мы вынуждены немного забежать вперед, чтобы ввести синтаксис и пояснить смысл раздела спецификации ссылочного типаопределения структурного типа. Строки типизированных таблиц обладают всеми характеристиками объектов в объектно-ориентированных системах, включая уникальные идентификаторы, которые могут использоваться для ссылок из других компонентов среды. В SQL :1999 поддерживаются три различных механизма присваивания уникальных идентификаторов экземплярам структурных типов, ассоциированных с такими таблицами (для всех строк таблицы, ассоциированной с данным структурным типом, используется один и тот же механизм). Уникальные идентификаторы экземпляров структурного типа могут представлять собой следующее:
значения, генерируемые системой автоматически;
значения некоторого встроенного типа SQL , которые должны генерироваться приложением при сохранении экземпляра структурного типа как строки типизированной таблицы;
значения, порождаемые из одного или нескольких атрибутов структурного типа.
Если в определении структурного типа присутствует раздел спецификации ссылочного типа, и указывается, что ссылочные значения будут генерироваться пользователями, то в определении структурного типа может присутствовать и раздел преобразования значений встроенного типа в значения ссылочного типа и наоборот.
Раздел преобразования типов может присутствовать только в определении индивидуального типа. Спецификации раздела обеспечивают возможности преобразования значений индивидуального типа в значения базового встроенного типа и наоборот.
В определении структурного типа может присутствовать раздел объявления сигнатур методов, ассоциируемых с определяемым структурным типом. Имеется возможность определять первичные методы, которые не применимы к любому супертипу определяемого структурного типа. Если определяемый тип является подтипом некоторого другого типа, то можно также определить подменяющие методы. Подменяющий метод имеет то же имя и тот же список аргументов, что и метод, определенный в некотором супертипе определяемого типа.
Исходный метод может быть определен как метод экземпляра, статический метод или метод-конструктор. Методы экземпляра действуют над экземплярами определяемого типа. Статические методы не используют экземпляры типа и не влияют на них; такие методы действуют над самим типом. Наконец, методы-конструкторы используются для инициализации экземпляров типа. Поскольку у неинстанциируемого типа не может быть экземпляров, для него могут быть определены только статические методы. Если при определении первичного метода не указывается его разновидность, этот метод считается методом экземпляра.
В сигнатуре метода указывается имя, по которому этот метод будет вызываться (вызывное имя – invocable name ). Кроме того, можно указать точное имя метода (specific name ), которое может быть использовано для уникальной идентификации метода, если его вызывное имя перегружено. Если у метода имеются какие-либо параметры, отличные от неявного параметра SELF , то в определении должен присутствовать заключенный в скобки список пар <имя_параметра, тип_параметра>, разделяемых запятыми. Поскольку методы являются функциями, требуется указать тип возвращаемого значения. Методы могут возвращать значения любого допустимого в SQL типа, даже структурного типа, ассоциированного с методом.
Наконец, у каждого метода имеется набор характеристик метода. Методы могут быть написаны на языке SQL или на любом из языков программирования, поддержка которых предусмотрена в стандарте SQL (Ada , C , COBOL , Fortran , MUMPS 77, Pascal , PL /1).
Язык Java поддерживается в стандарте несколько в иной манере, чем другие языки. Список параметров метода может быть определен в стиле, более соответствующем стилю SQL -подпрограмм (каждый параметр может принимать неопределенное значение, и не требуется параметр кода возврата). Для этого в качестве характеристики метода нужно указать PARAMETER STYLE SQL . Можно определить список параметров в стиле, более близком стилю различных языков программирования (параметру, который может принимать неопределенное значение, должен быть придан дополнительный параметр-индикатор, и должен быть явно определен выходной параметр кода ответа). В этом случае метод должен иметь характеристику PARAMETER STYLE GENERAL . Наконец, для методов, тела которых будут писаться на языке Java , нужно указать характеристику PARAMETER STYLE JAVA .
Любой метод может быть детерминированным или недетерминированным. Детерминированный метод всегда возвращает один и тот же результат, если вызывается с одним и тем же набором аргументов при одном и том же состоянии базы данных. По умолчанию методы считаются недетерминированными.
У каждого метода имеется характеристика, указывающая связь этого метода с SQL . Можно указать следующие варианты:
метод не содержит операторов SQL (NO SQL );
метод содержит операторы SQL , но не обращается к базе данных (CONTAINS SQL );
метод может производить выборку из базы данных, но не обновляет базу данных (READS SQL DATA );
в методе допускаются обновления базы данных (MODIFIES SQL DATA ).
По умолчанию принимается характеристика CONTAINS SQL . Наконец, для каждого метода можно определить его реакцию на аргументы, являющиеся неопределенными значениями. Если указывается RETURN NULL ON NULL INPUT , то метод всегда возвращает неопределенное значение, если значение любого из его аргументов является неопределенным. Если же указывается CALLED ON NULL INPUT (или если характеристика явно не задана), то метод всегда явно выполняется при вызове с любым набором аргументов.
Определение типизированной таблицы
С точки зрения синтаксиса оператор определения типизированной таблицы является частным случаем оператора создания базовой таблицы CREATE TABLE . Первой существенной особенностью оператора создания типизированной таблицы является обязательное наличие раздела OF , в котором указывается имя ранее определенного структурного типа. Строки типизированной таблицы являются экземплярами ассоциированного с таблицей структурного типа.
Далее, при определении типизированной таблицы можно объявить ее подтаблицей некоторой другой типизированной таблицы (имя супертаблицы указывается в разделе UNDER ). Супертаблица должна быть ассоциирована со структурным типом, являющимся непосредственным супертипом определяемой подтаблицы. Каждый столбец указанной супертаблицы наследуется подтаблицей; наследуются и характеристики столбцов супертаблицы – значения по умолчанию, ограничения целостности и т.д. Эти столбцы называются унаследованными столбцами подтаблицы, и они соответствуют атрибутам UDT подтаблицы, унаследованным от UDT супертаблицы. Кроме того, подтаблица будет содержать по одному столбцу для каждого собственного атрибута ассоциированного структурного типа. Такие столбцы подтаблицы называются заново определенными.
Как это принято в SQL , столбцы типизированной таблицы имеют порядковые номера. При этом унаследованные столбцы нумеруются до заново определенных и имеют те же номера, которые имели столбцы супертаблицы.
В определении типизированной таблицы разрешается указывать табличные ограничения целостности. Если определяемая таблица является подтаблицей некоторой супертаблицы, то в ней не допускается определение ограничения первичного ключа (PRIMARY KEY ). Однако, если определяется максимальная супертаблица, то в ее определении допускается спецификация PRIMARY KEY (с указанием одного или нескольких столбцов) или спецификация ограничения UNIQUE (с указанием одного или нескольких столбцов) в комбинации с указанием NOT NULL . В определении типизированной таблицы могут также содержаться спецификации ссылочных ограничений целостности.
Ссылки ( по значению) могут вести как на типизированную, так и на обычную таблицу.
В определении максимальной супертаблицы должна присутствовать спецификация “самоссылающегося” (self -referencing ) столбца, и самоссылающийся столбец, определенный в максимальной супертаблице, наследуется любой ее подтаблицей. Эта спецификация не может входить в определение подтаблицы. Семантика самоссылающихся столбцов обсуждается в этом подразделе ниже.
Наконец, для столбцов определяемой типизированной таблицы можно указывать опции столбцов. Опции столбца можно указывать только для заново определенных столбцов, для унаследованных столбцов это не допускается. Раздел области действия ссылок может входить в опции только заново определяемого столбца с типом REF (детали см. ниже). Для заново определяемого столбца некоторого типа символьных строк можно указать желаемый порядок на соответствующем наборе символов. Имеется опция для указания значения столбца по умолчанию, отличного от значения по умолчания соответствующего атрибута ассоциированного с определяемой таблицей структурного типа. Наконец, для заново определяемого столбца можно указать одно или несколько ограничений, включая проверочные ограничения.
Определяемые пользователями функции
В DB 2 имеется возможность создания определяемых пользователями функций (User -Defined Functions - UDF ) с использованием языков C , C ++ и Basic . UDF могут принимать параметры и могут быть использованы в любом выражении SQL , где предполагается наличие скалярного значения.
Поддерживается соглашение о передаче параметров UDF в поставляемую пользователем программу реализации функции. Создатель функции должен откомпилировать реализующую ее программу и поместить выполняемый файл в каталог, доступный серверу баз данных. После этого пользователь должен зарегистрировать UDF в каждой базе данных, где предполагается ее использование, путем выполнения оператора CREATE FUNCTION . Описание функции помещается в таблицы системного каталога. При каждом вызове функции ее реализация будет динамически загружаться и выполняться. DB 2 SQL позволяет “перегружать” имя функции, т.е. определять несколько функций с одним именем и разными типами параметров. При обработке вызова функции DB 2 вызывает функцию, сигнатура которой строго соответствуют типам аргументов вызова.
Определяемые пользователями типы
Думаю, что не стоит снова обосновывать потребность в UDT . Об этом много говорилось ранее в этой статье. Поэтому сразу перейдем к сути предложений SQL :1999. Как отмечалось выше, в стандарте поддерживается возможность определения пользователями двух разновидностей UDT – структурных типов (structured type ) и индивидуальных типов (distinct types ).
В DB 2 определяемые пользователями типы данных называются “индивидуальными типами” (“distinct type ”). В каждом из индивидуальных типов используется общее представление одного из встроенных типов (называемых “базовыми типами”), но может иметься собственный набор допустимых операций. Легко указать, какие из операций базового типа являются осмысленными для созданного на его основе индивидуального типа. Каждый встроенный оператор, такой как “+ ”, реализуется функций с тем же именем, что и оператор. Чтобы сделать этот оператор применимым к индивидуальному типу, нужно просто создать функцию с тем же именем, что и оператор, принимающую параметры и/или возвращающую результат индивидуального типа данных. Функция, реализующая оператор, может основываться на функции, реализующей встроенный оператор.
По мнению автора этой статьи,
По мнению автора этой статьи, после выпуска в 1997 г. системы Oracle 8 88, которая действительно претендовала на статус объектно-реляционной системы, впоследствии корпорация Oracle не стала уделять большого внимания развитию именно этих свойств своей системы. Лишь в системе Oracle 9 i (2002 г.) появились существенные дополнения. Поэтому в своем кратком описании мы в основном ограничимся свойствами Oracle 8, но в заключение подраздела обозначим и возможности, появившиеся в Oracle 9 i .
Предложения, касающиеся управления объектами и правилами
Создатели СУБД не в состоянии предвидеть все виды элементов данных, которые могут потребоваться приложениям. СУБД третьего поколения должны управлять разнообразными объектами, и авторы манифеста выдвигают четыре предложения, относящиеся к управлению объектами, конструкторам типов, наследованию, функциям и уникальным идентификаторам.
Предложение 1.1: Система типов СУБД третьего поколения должна быть богатой и разнообразной.
Все перечисленные механизмы являются желательными:
1) система абстрактных типов данных для создания новых базовых типов;
2) конструктор типа массив;
3) конструктор типа последовательность;
4) конструктор типа запись;
5) конструктор типа множество;58
6) функции как тип;
7) конструктор типа объединение;
8) рекурсивная композиция всех перечисленных выше конструкторов.
Первый механизм позволяет конструировать новые базовые типы в дополнение к стандартному набору типов, имеющемуся в большей части систем. Должно быть возможно определять типы битовых строк, точек, линий, комплексных чисел и т.д. Второй механизм позволяет использовать массивы элементов данных. Обычным свойством массивов является отсутствие возможности вставить новый элемент в середину, сдвинув все последующие элементы. В некоторых приложениях такая вставка бывает необходимой, и конструктор третьего вида поддерживает подобные последовательности. Четвертый механизм позволяет группировать элементы данных в записи. Пятый механизм требуется для создания неупорядоченных наборов элементов данных или записей. Шестой механизм – функции (методы) – обсуждается в предложении 1.3; желательно, чтобы СУБД поддерживала такие конструкции. Следующий механизм позволяет создавать элементы данных, которые могут принимать значения одного из нескольких типов.59
Последний механизм позволяет рекурсивно комбинировать конструкторы типов для поддержки сложных объектов, обладающих внутренней структурой.
Более того, в отличие от систем второго поколения, последний примененный конструктор типов не обязан быть конструктором множеств.60
Возможно, со временем станут желательными и дополнительные конструкторы типов. Например, системы обработки транзакций управляют очередями сообщений. Поэтому может возникнуть необходимость в конструкторе, создающем очереди.
Системы второго поколения обладают лишь частью перечисленных конструкторов типов, и сторонники объектно-ориентированных баз данных утверждали, что для поддержки всех этих возможностей должны появиться качественно новые СУБД. Авторы манифеста придерживались другой точки зрения. В манифесте утверждается, что все обсуждаемые конструкторы типов можно добавить к реляционным системам как естественное расширение, и что технология этого расширения достаточно хорошо продумана. Более того, уже в то время начали появляться коммерческие реляционные системы с некоторыми из перечисленных возможностей.
Предложение 1.2: Наследование – хорошая идея.
Возможность организации типов в иерархию наследования является хорошей идеей. Более того, авторы манифеста считали, что существенно множественное наследование, так что иерархия наследования должна представляться ориентированным графом. Поддержка только единичного наследования оказывается недостаточной для адекватного моделирования подавляющего большинства ситуаций. Отмечается, что, хотя в Первом манифесте и защищается идея наследования, множественное наследование там приводится как необязательная возможность.
Желательно также иметь наборы, для которых не задаются дополнительные поля. Например, набор TEENAGER (подросток) можно было бы определить как набор, состоящий из таких же элементов данных, что и PERSON , но обладающий ограничениями на возраст. Опять-таки, уже создавались прототипы, демонстрирующие, как добавлять эти возможности к реляционным системам, и авторы манифеста ожидали, что коммерческие реляционные системы будут развиваться в этом направлении.61
Предложение 1.3: Функции, в том числе процедуры и методы баз данных, и инкапсуляция – хорошие идеи.
В системах второго поколения имеется лишь ограниченная поддержка функций и инкапсуляции. Например, в SQL над таблицами возможны только операции, осуществляемые функциями create , alter и drop .62 Абстракция таблицы доступна только путем выполнения одной из перечисленных функций.
Очевидно, что выгоды, предоставляемые инкапсуляцией, должны стать доступными для разработчиков приложений, чтобы те могли ассоциировать функции с пользовательскими наборами данных. Например, должна иметься возможность ассоциировать функции HIRE ( EMPLOYEE ) , FIRE ( EMPLOYEE ) и RAISE - SAL ( EMPLOYEE ) (нанять, уволить служащего и повысить ему зарплату) с уже знакомым набором данных EMPLOYEE . Если пользователям не разрешен прямой доступ к набору EMPLOYEE , а вместо этого предоставлены упомянутые функции, то вся информация о внутренней структуре объектов класса EMPLOYEE инкапсулируется внутри этих функций.63
Использование инкапсуляции дает административные преимущества путем поощрения модульности и регистрации функций вместе с инкапсулируемыми данными. Если набор EMPLOYEE изменяется так, что его предыдущее содержимое нельзя определить как представление, весь код, который необходимо изменить, локализован в одном месте, следовательно, его проще модифицировать.
В защищенных или распределенных системах применение инкапсуляции часто дает выигрыш в производительности. Например, функции HIRE ( EMPLOYEE ) в процессе выполнения несколько раз может потребоваться доступ к базе данных. Если HIRE ( EMPLOYEE ) задана как функция, которая должна быть выполнена сервером базы данных внутренним образом, то между приложением и СУБД состоится только один цикл обмена сообщениями. С другой стороны, если функция запускается из программы пользователя, один цикл обмена сообщениями потребуется для каждого доступа. 64
Наконец, такие функции могут быть унаследованы и, возможно, переопределены в иерархии наследования. Другими словами, функция HIRE ( EMPLOYEE ) может быть автоматически применена к набору STUDENT - EMPLOYEE .
Если воспользоваться возможностью переопределения, функцию HIRE для набора STUDENT - EMPLOYEE можно переписать. Словом, использование инкапсулированных функций крайне желательно. Однако авторы манифеста приводят три замечания.
Во-первых, пользователям следует писать функции на языке программирования высокого уровня и получать доступ к базам данных при помощи непроцедурного языка доступа высокого уровня. Язык доступа может быть встроен в язык программирования средствами препроцессора или реализован как прямое расширение языка программирования. Прямой доступ к внутренностям системы должен стать допустимым, но крайне нежелательным способом написания функций.65
Второе замечание касается понятия непрозрачных типов. Некоторые энтузиасты идеи объектно-ориентированных баз данных утверждают, что должен быть только один способ, с помощью которого пользователь может получить доступ к набору – выполнение одной из функций, применимых к набору. Такое ограничение игнорирует потребности языка запросов, среде выполнения которого требуется непосредственный доступ к каждому элементу данных. Необходим механизм, делающий типы прозрачными, чтобы к элементам данных этих типов можно было получить доступ через язык запросов.
Последнее замечание касается коммерческого рынка. Все крупнейшие поставщики СУБД второго поколения уже поддерживают функции, написанные на языке программирования высокого уровня (обычно на поддерживаемом поставщиком 4GL ), которые могут производить обращения к СУБД в терминах SQL . Более того, эти функции могут быть использованы для инкапсуляции доступа к данным, которыми они управляют. Поставщикам коммерческих реляционных систем осталось поработать над поддержкой наследования функций.
Предложение 1.4: Уникальные идентификаторы (UID ) записей должны задаваться СУБД только в том случае, когда недоступен определенный пользователем первичный ключ.
В системах второго поколения поддерживается понятие первичного ключа – заданного пользователем уникального идентификатора.
Неизменный первичный ключ лучше присвоенного системой UID , потому что обозначает нечто естественное, понятное человеку. При обмене данными или отладке это может быть значительным преимуществом. Если для набора первичный ключ недоступен, появляется необходимость в присвоенном системой уникальном идентификаторе. Некоторые наборы данных не обязательно обладают системно заданными UID , так что построение систем с принудительной уникальной идентификацией, вероятнее всего, окажется нежелательным.
Предложение 1.5: Правила (триггеры, ограничения) станут одной из ключевых характеристик будущих систем.
Правила не следует ассоциировать с определенными функциями или наборами. Исследователи объектно-ориентированных баз данных обычно игнорировали необходимость правил. На вопрос о правилах энтузиасты ООБД отвечали либо молчанием, либо предложением внедрять их путем включения кода для их поддержки в одну или несколько функций, работающих с набором.
С точки зрения авторов манифеста, имеется только одно разумное решение: правила должны поддерживаться СУБД, но не быть привязаны ни к какой функции и ни к какому набору. Из этого положения следуют два факта. Во-первых, парадигма ООБД “все выражается методами” просто не применима к правилам. Во-вторых, нельзя предоставлять непосредственный доступ к внутренним интерфейсам СУБД ниже уровня активации правил (иначе пользователи смогут обходить систему, включающую правила в нужное время).
Ко времени написания Второго манифеста уже существовали продукты поставщиков систем второго поколения, отвечающие приведенному предложению. Тем самым, в вопросах, касающихся этого предложения, коммерческий реляционный рынок опередил уровень исследований ООБД.
Предложения, касающиеся увеличения функциональных возможностей СУБД
Как уже отмечалось, системы третьего поколения не должны делать шаг назад, то есть они должны вобрать в себя все возможности, предоставляемые системами второго поколения. Особого внимания заслуживают язык запросов, спецификация множеств элементов данных и независимость данных. Следующие четыре предложения, касаются перечисленных вопросов.
Предложение 2.1: Все виды программируемого доступа к базам данных должны осуществляться через непроцедурный язык доступа высокого уровня.
В литературе, посвященной ООБД, как правило, недооценивается критическая важность высокоуровневых языков доступа к данным, по выразительной силе не уступающих реляционному языку запросов. Например, в Первом манифесте
выдвигается предложение, что СУБД должна предоставлять возможность интерактивного доступа к данным в любой удобной форме. Авторы Второго манифеста делают более сильное утверждение: выразительная сила языка запросов должна присутствовать в любом интерфейсе программируемого доступа; не должно быть других способов доступа к данным СУБД. В перспективе такой сервис может быть обеспечен путем добавления конструкций языка запросов к различным языкам программирования со стабильным хранением данных. В ближайшем будущем этот сервис может быть обеспечен путем встраивания языка запросов в обычные языки программирования.
Многие исследователи OODB утверждают, что для приложений, ради которых они разрабатывают свои системы, желательна навигация к искомым данным с использованием низкоуровневого процедурного интерфейса. В частности, им требуется интерфейс с СУБД, с помощью которого можно получать доступ к определенным записям. Один или более элементов данных записи будет иметь тип “ссылка на запись в каком-то другом наборе”, обычно представляемым своего рода указателем на запись другого набора, то есть идентификатором объекта. Далее, приложение выберет один из указателей для создания новой текущей записи. Этот процесс будет продолжаться до тех пор, пока приложение не доберется до искомых данных.
По мнению авторов Второго манифеста, подобные интерфейсы неудобны, и использовать их не следует. Во-первых, когда программист осуществляет навигацию к искомым данным, он заменяет функции оптимизатора запросов написанными вручную вызовами более низкого уровня. История наглядно продемонстрировала, что хорошо написанный и хорошо настроенный оптимизатор почти во всех случаях добивается лучших результатов, чем написанные вручную вызовы. Далее, если изменится некоторое число индексов или данные в кластере будут реорганизованы, навигационный интерфейс не сможет автоматически приспособиться к переменам. Значит, если изменятся физические пути доступа к данным, программисту придется модифицировать программу. С другой стороны, оптимизатор запросов просто создает новый план, который оптимизируется для новой среды.
Авторы Второго манифеста утверждают, что их подход приносит выигрыш в производительности по сравнению с использованием низкоуровневых интерфейсов. Это утверждение, на первый взгляд, противоречит интуиции и нуждается в объяснениях. Подавляющее большинство энтузиастов ООБД считает, что указатель должен быть мягким, т.е. его значение не должно меняться, даже если элемент данных, на который он указывал, был передвинут. Эта характеристика, называемая позиционной независимостью, является желательной, так как она позволяет перемещать элементы данных, не меняя при этом структуры базы данных. Перемещения элементов данных часто неизбежны при реорганизации базы данных или восстановлении после сбоев. Таким образом, энтузиасты ООБД рекомендуют использовать в качестве указателей позиционно независимые уникальные идентификаторы. В этом случае для перехода по указателю необходим доступ к хэшированной или индексированной структуре уникальных идентификаторов.
В SQL -представлении, пара (имя-отношения, ключ) в точности является позиционно независимым уникальным идентификатором, задающим тот же хэшированный или индексированный просмотр. Все накладные расходы, связанные с синтаксисом SQL , с высокой степенью вероятности придутся на время компиляции.
Поэтому авторы Второго манифеста утверждают, что использование интерфейсов низкого уровня для возвращения единственного элемента данных дает в лучшем случае лишь микроскопический выигрыш в производительности. Если же возвращается несколько элементов данных, то замещение запроса высокого уровня множеством вызовов низкого уровня может снизить производительность из-за расходов на организацию вызовов от приложения к СУБД.
Наконец, энтузиасты ООБД часто утверждают, что программисты, например, САПР, хотят собственноручно осуществлять навигацию, и поэтому система должна поощрять ее при помощи интерфейсов низкого уровня. Да, некоторые программисты могут предпочитать навигацию. Были такие, которые отказывались переходить с языка ассемблера на языки высокого уровня, были и те, кто отказывался переходить к реляционным системам – на новых системах задачи были не столь сложными, а, значит, работа не столь интересная. Эти программисты думали, что смогут работать лучше, чем компиляторы и оптимизаторы. Авторы манифеста считают, что аргументы против навигации достаточно убедительны и что некоторым программистам просто не мешает подучиться.
Предложение 2.2: Должно быть по крайней мере два способа спецификации наборов: посредством перечисления членов и путем использования языка запросов для задания членов.
В литературе по ООБД предлагается задание множеств перечислением, средствами связанного списка или массива идентификаторов членов. Авторы манифеста полагают, что такая спецификация не является лучшим выбором.
Имеются, по меньшей мере, два способа задания наборов, таких как множества, массивы, последовательности и т.д. Их можно определять “экстенсионально” при помощи набора указателей или “интенсионально” при помощи выражения. Интенсиональная спецификация поддерживает автоматическое определение принадлежности к множеству, что желательно для большинства приложений. Экстенсиональная спецификация предпочтительна лишь в тех случаях, когда между членами множества отсутствует структурная связь или когда автоматическое определение членства нежелательно.
При интенсиональной спецификации оптимизатор запросов может производить семантические преобразования. Это позволяет выбирать пути доступа, лучшие для данного запроса. Никаких ограничений, налагаемых структурами указателей, не существует. Таким образом, полномочия по принятию решений по вопросам физического представления делегируются администратору базы данных. Администратор может решать, какие способы доступа следует поддерживать (например, связанные списки или массивы указателей).
Оба представления необходимы, но предпочтение должно отдаваться интенсиональному. С другой стороны, энтузиасты ООБД, как правило, рекомендуют использовать лишь экстенсиональные методы. В середине 70-х годов преимуществам автоматического задания множеств посвящалось немало внимания. Чтобы не сделать шаг назад, системы третьего поколения должны отдавать предпочтение автоматическим множествам.
Предложение 2.3: Существенно наличие обновляемых представлений.
Существует очень немного статических баз данных – большая часть данных постоянно изменяется. При изменениях наборов данных может потребоваться модификация программ. Очевидно, что инкапсуляция доступа к базе данных в функции и инкапсуляция функций в один набор была бы полезным шагом. Это позволило бы легко выявлять функции, в которые необходимо внести изменения. Однако это решение не является достаточным. Если изменяется схема базы данных, то на переписывание затронутых этими изменениями функций могут уйти недели или даже месяцы. В это время база данных не может просто перестать работать.
Гораздо лучшим подходом является поддержка виртуальных наборов (представлений). В системах второго поколения поддерживались некоторые возможности в данной области, что было продвижением вперед по сравнению с системами первого поколения. К сожалению, обновление реляционных представлений часто оказывается невозможным. Системы третьего поколения должны демонстрировать лучшее поведение при обновлении представлений.
Традиционным способом поддержки обновления представлений заключается в том, что для каждого набора элементов данных, над которым может быть построено обновляемое представление, поддерживается группа функций, посредством которых осуществляется весь доступ к набору.
Автор определения представления должен вносить необходимые изменения в каждую из этих функций. Это влечет за собой значительные расходы на сопровождение программ, а также не позволяет выполнять обновление с помощью языка запросов. В качестве альтернативы такому подходу можно выдвинуть подходящую систему правил. Преимущество второго подхода заключается в том, что для обеспечения семантики обновления снимка требуется задать только одно (или несколько) правил. Это намного проще, чем внесение изменений в набор функций.66
Элементы виртуального набора не обязаны иметь уникальный идентификатор, так как физически их не существует. Следовательно, вряд ли можно требовать, чтобы каждая запись в наборе обладала уникальным идентификатором, как это делается во многих существующих прототипах ООБД.67
Предложение 2.4: Показатели производительности не имеют почти ничего общего с моделями данных и не должны в них проявляться.
Основными параметрами, по которым оценивается производительность работы с использованием как SQL , так и спецификаций более низкого уровня, являются следующие показатели:
объем работ по оптимизации настройки СУБД с целью повышения ее эффективности;
использование в СУБД методов компиляции;
местонахождение буферного пула (в адресном пространстве клиента или СУБД);
доступные типы индексирования;
производительность интерфейса клиент СУБД;
поддерживаемая кластеризация.
Эти вопросы не имеют ничего общего с моделью данных или с использованием языков высокого уровня типа SQL вместо навигационного интерфейса низкого уровня. Например, тактика кластеризации связанных объектов представляется как важная черта ООБД. Однако эта тактика использовалась в системах баз данных уже многие годы, например, являлась основным средством в большинстве методов доступа IMS . Следовательно, кластеризация является вопросом физического представления и не имеет ничего общего с моделью данных СУБД. Аналогично, с моделью данных не связаны решения о том, должна ли система строить индексы для уникальных идентификаторов, и следует ли ей буферизовать записи базы данных на клиентской машине или даже в пользовательском пространстве прикладной программы.При известном потоке запросов к базе данных следует пытаться достичь максимальной производительности. Действенность конкретных методов зависит от специфики приложений. Эти методы пригодны для любой системы баз данных.
Предложения, следующие из необходимости открытости системы
Обратим внимание на прикладной программный интерфейс (Applications Programming Interface – API ), посредством которого программа пользователя будет общаться с СУБД.
Предложение 3.1: СУБД третьего поколения должны быть доступны из различных языков программирования высокого уровня.
Некоторые разработчики систем утверждают, что СУБД должна быть тесно привязана к определенному языку программирования. Например, они говорят, что функция должна возвращать один и тот же результат независимо от того, была ли она выполнена в программе пользователя для временных данных или внутри СУБД для стабильных данных. Этого можно достичь только в том случае, если модель выполнения СУБД идентична модели выполнения конкретного языка программирования. Авторы манифеста считают, что это неверный подход.
Во-первых, невозможно договориться, какой именно язык программирования следует использовать. Приложения кодируются и будут кодироваться на различных языках, и на горизонте пока не видно языка программирования Esperanto . Отсюда следует необходимость в многоязычной СУБД.
Имеется еще одна причина, по которой открытая СУБД должна быть многоязычной. СУБД должна предоставлять доступ для различных внешних прикладных подсистем, например, Lotus 1-2-3. Такие подсистемы будут кодироваться на различных языках программирования – вот еще один аргумент в пользу многоязычности.
Предложение 3.2: Язык “X с поддержкой стабильных данных” (для различных X ) является хорошей идеей. Языки будут поддерживаться над единой СУБД благодаря расширениям компилятора и (более или менее) сложной системе времени выполнения.
В интерфейсах систем второго поколения с языками программирования препроцессор использовался отчасти потому, что на ранней стадии разработчики СУБД не сотрудничали с разработчиками компиляторов. Более того, у сохранения независимости языка СУБД от языков программирования есть свои преимущества (например, СУБД и языки программирования можно независимо расширять и тестировать). Однако получавшиеся интерфейсы не отличались дружественностью и уже в 1977 году были охарактеризованы как “попытки приклеить яблоко к блину”.
Поставщики обычно концентрировали свои усилия на создании элегантного интерфейса между своими языками четвертого поколения и сервисами баз данных. Очевидно, что не менее элегантные интерфейсы можно создать и для универсальных языков программирования.
Во-первых, очень важно установить более точное соответствие между системами типов. Именно в этом состоит основная проблема современных реализаций встроенного SQL , а не синтаксиса SQL . Во-вторых, было бы хорошо предоставить возможность сделать любую переменную в программе пользователя стабильной. Значения стабильных переменных не утрачиваются даже после окончания работы программы. В последнее время проявляется большая заинтересованность в подобных интерфейсах.
Как отмечалось ранее, функции должны кодироваться путем включения вызовов к СУБД, выраженных на языке запросов. Следовательно, и для “X с поддержкой стабильных данных” также требуются средства выражения на языке запросов. Такие запросы могут быть выражены в нотации, соответствующей специфике языка программирования. Системы времени выполнения должны принимать и обрабатывать такие запросы и доставлять результаты обратно в программу.
Будет создано множество разнообразных “X с поддержкой стабильных данных”. Для каждого из них потребуются свои модификации компилятора и системы времени выполнения. Все системы времени выполнения будут подключены к общей СУБД.68 Очевиден вопрос “Как выражать запросы к этой общей СУБД?”. Ответ дается в следующем предложении.
Предложение 3.3: Хорошо это или плохо, но SQL становится интергалактическим языком данных.
На сегодня SQL предоставляет универсальный способ выражения запросов. При создании первых коммерческих объектно-ориентированных баз данных этот факт не учитывался, и потом пришлось встраивать в продукты запросные системы на основе запросов SQL . К сожалению, многие продукты не дожили до окончания этой работы. Хотя перед SQL и стоит множество мелких проблем, он необходим для коммерческой жизнеспособности. Любая компания-производитель объектно-ориентированных систем баз данных, желающая, чтобы ее продукт оказывал влияние на рынок, должна понять, что покупатели голосуют своими долларами за SQL .
Более того, SQL является разумной кандидатурой для новых функций, предлагаемых в этой работе. Конечно, для некоторых приложений и языков программирования могут оказаться адекватными и другие языки запросов.
Предложение 3.4: Запросы и ответы на них должны образовывать нижний уровень коммуникаций между клиентом и сервером.
В условиях, когда пользователь находится за рабочей станцией и взаимодействует с данными на удаленном сервере, встает вопрос о протоколах взаимодействия рабочей станции и сервера. Энтузиасты ООБД обсуждают, должны ли посылаться запросы на единичные записи, единичные страницы или должен использоваться иной механизм. Точка зрения авторов манифеста крайне проста: выражения на языке запросов должны образовывать нижний уровень коммуникаций. Конечно, если набор запросов можно упаковать в функцию, пользователь может использовать удаленный вызов для выполнения функции на сервере. Эта возможность желательна, поскольку она позволяет обойтись менее чем одним сообщением на запрос.
Принципы СУБД третьего поколения
Первый принцип касается определения СУБД третьего поколения: помимо традиционных услуг по управлению данными, СУБД третьего поколения должны обеспечивать поддержку более богатых структур объектов54 и правил.
Более богатая структура объектов характеризует средства, необходимые для хранения и манипулирования нетрадиционными элементами данных (тексты, пространственные данные). Помимо этого, создателям приложений следует предоставить возможность задавать группу правил, касающихся элементов данных, записей и наборов.Ссылочная целостность в контексте реляционных баз данных представляет собой простой пример такого правила; однако существует множество более сложных правил.
Для успешного решения большинства задач СУБД должна предоставлять услуги в области данных, объектов и правил. Хотя, возможно, на рынке найдется ниша и для систем с меньшими возможностями, для достижения коммерческого успеха в 90-е годы СУБД должна предоставлять сервисы во всех трех перечисленных областях.55
Второй принцип: СУБД третьего поколения должны включить в себя СУБД второго поколения.
Системы второго поколения внесли решающий вклад в двух областях: непроцедурный доступ и независимость данных. И эти достижения не должны быть отброшены в системах третьего поколения.
Существует точка зрения, что имеются приложения, которым никогда не потребуется выполнять запросы из-за присущей им простоты доступа к СУБД. В качестве примера часто предлагаются САПР. Делается вывод, что будущим системам язык запросов не потребуется и, следовательно, отпадает необходимость включения систем второго поколения. Авторы Второго манифеста беседовали со многими разработчиками САПР, интересующимися базами данных, и все они отмечали необходимость языка запросов.
Другим улучшением, внесенным системами второго поколения, стало введение понятия независимости данных. В области физической независимости данных системы второго поколения автоматически поддерживают согласованность всех путей доступа к данным, и оптимизатор запросов автоматически выбирает лучший способ выполнения любой выданной пользователем команды.
Кроме того, системы второго поколения обеспечивают представления баз данных, посредством которых пользователь может быть изолирован от изменений анализируемого множества наборов, хранящихся в базе данных. Эти характеристики значительно снизили объем программной поддержки, которая должна быть обеспечена приложениями, и от них не стоит отказываться.
Третий принцип состоит в том, что СУБД третьего поколения должны быть открыты для других подсистем.
Иными словами, любая СУБД, рассчитывающая на широкую сферу применения, должна быть оснащена языком четвертого поколения (4GL )56, разнообразными инструментами поддержки принятия решений57, дружественным доступом из многих языков программирования, дружественным доступом из популярных подсистем, таких как LOTUS 1-2-3, интерфейсами с графическими бизнес-пакетами, возможностью запуска приложений из базы данных на другой машине и возможностью организации распределенной базы данных. Весь набор инструментов и СУБД должен эффективно функционировать на разнообразных аппаратных платформах с различными операционными системами.
Из этой посылки исходят два следствия. Во-первых, любая удачная система третьего поколения должна поддерживать большую часть перечисленного инструментария. Во-вторых, СУБД третьего поколения должны быть открытыми, то есть должны допускать реализацию доступа из дополнительных инструментов, функционирующих в различных средах. Более того, каждая система третьего поколения должна легко объединяться с другими СУБД для создания распределенных систем баз данных.
Промежуточные замечания
По мнению автора этой статьи, основной интерес в статье Дона Чемберлина представляет то, что в ней показана возможность создания нетрадиционных приложений при наличии минимальных объектных расширений в DB 2 for Common Servers . В частности, статья заставляет задуматься о том, нужны ли на самом деле дальнейшие расширения.
Тем не менее, компания IBM выполнила практически все свои обещания, и ниже мы кратко обсудим дополнительные объектные расширения, реализованные в следующих версиях DB 2 UDB .
Размышления о будущем
Все возможности, описанные в статье [11], были доступны в DB 2 for Common Servers с июля 1995 г. IBM планировала распространить те же возможности и на других членов семейства DB 2. Особенно важно то, что через год после выпуска компанией IBM ее первой объектно-реляционной системы в лабораториях IBM производилась интенсивная разработка дополнительных объектно-реляционных средств, включая следующее:
абстрактные типы данных с наследованием;
UDF с телом, написанным на SQL;
UDF, результатом которых являются таблицы;
возможность обращаться со строкой таблицы как с объектом, возможно содержащим ссылки на другие сроки-объекты;
дополнительные расширители для таких специализированных типов данных, как временные ряды и географические данные.
Синергия
Большие объекты, определяемые пользователями типы и функции, ограничения и триггеры представляют в отдельности мощные возможности. Но истинная объектно-реляционная мощность DB 2 происходит из синергии этих возможностей. В качестве примера рассмотрим, как объектно-реляционные возможности DB 2 могут быть использованы на обеспечения хранения в базе данных многоугольников.
Поскольку отсутствует предопределенный тип данных “многоугольник”, то прежде всего нужно понять, каким образом многоугольники будут представляться в базе данных. Поскольку многоугольники потенциально могут быть довольно большими, для их представления должен использоваться тип больших объектов BLOB . Но хотелось бы отличить это представление от других объектов типа BLOB , и поэтому мы создадим индивидуальный тип POLYGON :
CREATE DISTINCT TYPE POLYGON AS BLOB(1M);
Можно выбрать различные реальные представления многоугольников внутри большого объекта. Например, это может быть последовательность чисел, первое из которых задает число вершин многоугольника, а следующие содержат координаты вершин. После создания индивидуального типа желательное поведение многоугольников может быть указано путем создания набора соответствующих UDF . По крайней мере, одна из этих функций должна быть “конструктором”, создающим многоугольник на основе более простых типов, таких как POINT или DOUBLE . Работа функции-конструктора состоит в упаковке примитивных частей многоугольника в BLOB с последующим преобразованием типа BLOB к типу POLYGON (для этого следует использовать сгенерированную системой функцию преобразования типов POLYGON ( BLOB )) . Ниже перечислены некоторые из UDF , задающие поведение типа POLYGON . Эти функции могут быть написаны, например, на языках C или C ++.
degree(Polygon) returns Integer;
area(Polygon) returns Double;
perimeter(Polygon) returns Double;
rotate(Polygon, Double) returns Polygon;
intersect(Polygon, Polygon) returns Polygon;
Теперь можно создавать таблицы со столбцами типа POLYGON . Например, следующий оператор можно было бы использовать в налоговом управлении для создания таблицы, в которой должны регистрироваться земельные участки, находящиеся в частной собственности:
CREATE TABLE properties
(taxid Char(6) PRIMARY KEY,
owner Varchar(32),
assessment Dollars,
parcel Polygon );
Для нахождения собственников больших участков можно использовать следующий запрос на языке SQL :
SELECT owner, area(parcel)
FROM properties
WHERE area(parcel) > 20000;
Наиболее эффективный способ выполнения этого запроса мог бы базироваться на использовании индекса, обеспечивающего прямой доступ к участкам по значению их площади. Поддержка индексов на UDF находится в планах развития DB 2, но пока ее нет. Но возможно другое решение, позволяющее выполнить запрос с той же эффективностью. Добавим к таблице PROPERTIES новый столбец, который должен содержать заранее вычисленный размер площади, и создадим триггеры для поддержки корректных значений этого столбца. Для добавления столбца можно использовать оператор SQL
ALTER TABLE properties
ADD COLUMN area Double;
Теперь определим триггеры, которые активируются при выполнении над таблицей PROPERTIES операторов INSERT и UPDATE . Вот как могло бы выглядеть определение триггера для INSERT :
CREATE TRIGGER insertprop
NO CASCADE
BEFORE INSERT ON properties
REFERENCING NEW AS newrow
FOR EACH ROW MODE DB2SQL
SET newrow.area = area(newrow.area);
Поскольку площадь каждого участка автоматически вычисляется и хранится в отдельном столбце, для убыстрения доступа к участкам по значению их площади можно создать индекс на столбце AREA :
CREATE INDEX proparea ON properties(area);
Теперь перепишем запрос в форме, которая даст возможность DB 2 использовать этот индекс:
SELECT owner, area
FROM properties
WHERE area > 20000;
Составные типы данных
IUS позволяет определять новые составные типы данных. Составные типы могут иметь структуру записи, множества, мультимножества или списка. Структуры данных могут быть вложенными, то есть значениями столбцов таблиц могут быть записи83, множества или списки, состоящие в свою очередь из атомарных или структурных значений.
Например, значениями следующего типа данных являются ФИО человека:
CREATE ROW TYPE fio_t
( last_name CHAR(40),
first_name CHAR(40),
second_nameCHAR(40) )
Определенный таким образом составной тип может использоваться наравне и с предопределенными типами для определения столбцов таблицы. Для доступа к отдельным полям значений типа записи используется традиционная “точечная” нотация.
Имеется возможность определения трех видов типов коллекций: множеств, мультимножеств и списков (иными словами, имеются конструкторы этих типов). Поскольку по определению все элементы множества должны быть различны, ни в одно значение типа множества не может входить NULL 84.
Хотя по определению среди элементов мультимножества могут содержаться дубликаты, в IUS значения типа мультимножества, как и значения-множества не могут содержать неопределенных значений.85
Средствами прямого SQL можно осуществлять доступ к значениям-множествам (и мультимножествам) только как к единому целому. Доступ к элементам множества возможен только при использовании встроенного SQL (вернее, варианта SQL , поддерживаемого в IUS ) или языка определения хранимых процедур (SPL ). Основная идея состоит в том, что множество представляется в виде производной таблицы, каждая строка которой содержит один элемент множества. Любую операцию с множествами можно выразить в терминах реляционных операций над производными таблицами.
Список является упорядоченным набором элементов, в котором допускается наличие дубликатов. Список отличается от мультимножества тем, что для каждого элемента списка имеется порядковый номер (нумерация начинается с единицы). В значениях-списках, как и в значениях-множествах (и мультимножествах), запрещается наличие элементов со значением NULL .86 Доступ к элементам значений-списков столбцов таблицы базы данных, как и к значениям-множествам и мультимножествам, обеспечивается только при использовании встроенного SQL или SPL .
Создание иерархий таблиц
Иерархии таблиц используются для хранения объектов и для обеспечения возможности изменять эти объекты на уровне SQL . С концептуальной точки зрения, в иерархии таблиц отражается соответствующая иерархия типов. Однако типы, подобно библиотекам классов, могут использоваться в различных контекстах, поэтому не все типы из иерархии типов обязаны присутствовать в соответствующей иерархии таблиц. Единственным требованием является то, что при образовании иерархии таблиц должно использоваться подмножество ассоциированной иерархии типов.
При определении типизированной таблицы нужно явно специфицировать дополнительный столбец, в котором будут храниться значения объектных идентификаторов (OID ) каждого объекта (строки), содержащейся в таблице. Столбец OID создается как первый столбец таблицы, и за ним следуют столбцы, соответствующие атрибутам типа таблицы. Объектные идентификаторы используются в операциях разыменования (dereference ), т.е. обеспечивают возможность добраться до строки по ссылке и преобразовать ее в экземпляр (значение) структурного типа. Объектные идентификаторы относятся к ссылочному типу. Они строго типизированы (т.е. для них не допускаются неявные преобразования типов). Чтобы преобразовать один ссылочный тип в другой, требуется промежуточное преобразование OID к одному из базовых типов.
Специальные методы хранения, поиска и индексации
В IUS можно определять новые базовые типы данных одновременно с введением специальных алгоритмов хранения, доступа и индексирования, которые отличаются от стандартных алгоритмов, реализованных в сервере87. Для введения нового базового типа данных с нестандартными методами доступа нужно определить набор серверных функций, реализующий для нового типа алгоритмы доступа, просмотра, выделения памяти и т.д. Эти функции должны быть написаны на языке C и скомпилированы в объектный формат. Далее надо описать новый базовый тип данных, и указать функции, реализующие для этого типа алгоритмы извлечения и записи на диск значений данного типа.
Ссылочные значения и REF -типы
Понятия ссылочных значений и ссылочных (REF ) типов являются по существу неразделимыми. В SQL :1999 ссылочный тип может использоваться в качестве типа данных столбцов обычных таблиц, атрибутов структурных типов и т.д. – словом, везде, где можно использовать другие типы данных SQL . Значения местоположений ссылочного типа всегда являются ссылочными значениями строк типизированных таблиц (т.е. значениями самоссылающихся столбцов этих строк).
В SQL :1999 обеспечиваются три механизма назначения уникальных идентификаторов экземплярам структурных типов, ассоциированных с типизированными таблицами. Во всех типизированных таблицах, ассоциированных с данными структурным типом, должен использоваться один и тот же механизм. Предоставляются следующие альтернативы выбора ссылочных значений, которые могут являться
значениями некоторого встроенного типа SQL , которые должны генерироваться приложением каждый раз при сохранении экземпляра структурного типа как строки типизированной таблицы;
значениями, порождаемыми из одного или нескольких атрибутов структурного типа;
значениями, автоматически генерируемыми системой.
При определении структурного типа, который предназначается для определения одной или нескольких типизированных таблиц, необходимо задать спецификацию ссылочного типа. При определении типизированных таблиц, необходимо указать соответствующую спецификацию самоссылающегося столбца (конечно, эта спецификация логически избыточна).
Если для некоторого структурного типа выбран вариант пользовательской генерации ссылочных значений, то ответственность за поддержание уникальности таких значений лежит на пользователе. Конечно, ограничения PRIMARY KEY или UNIQUE , определенные на уровне максимальной супертаблицы семейства типизированных таблиц, могут гарантировать отсутствие в любой таблице этого семейства дублирующих ссылочных значений, но в SQL :1999 отсутствуют какие-либо средства, предотвращающие повторное использование ссылочных значений из удаленных строк в самоссылающихся столбцах новых строк.
В этом случае в определении структурного типа может присутствовать конструкция, специфицирующая функции преобразования значений встроенного типа в значения ссылочного типа и наоборот. В этой конструкции вводятся имена двух SQL -функций, первая из которых служит для преобразования ссылочных значений (в нашем примере, значений целого типа), обеспечиваемых приложением, к соответствующему REF -типу при вставке или обновлении строк типизированной таблицы. Вторая функция преобразует значения REF -типа к соответствующему встроенному типу данных при выборке строк из типизированной таблицы. Система автоматически генерирует обе подпрограммы, и упомянутая конструкция позволяет лишь назначить подпрограммам имена. Если эта конструкцияявно не включается в определение структурного типа со ссылочными значениями, генерируемыми пользователями, то имена подпрограммам назначаются системой.
Если для структурного типа выбирается альтернатива порождения ссылочных значений, то система использует для порождения ссылочных значений значения неявно указанных столбцов (соответствующих явно указанным атрибутам ассоциированного структурного типа). При этом остаются все упомянутые выше проблемы, хотя в этом случае явно требуется объявление ограничений PRIMARY KEY или UNIQUE для соответствующего набора столбцов.
Наконец, при выборе последней альтернативы (системно-генерируемые ссылочные значения) каждой строке, вставляемой в типизированную таблицу, ассоциированную с соответствующим структурным типом, присваивается уникальный идентификатор. Это значение сохраняется в самоссылающемся столбце и может быть использовано любым приложением для уникальной идентификации данной строки во все время жизни таблицы.
Самоссылающиеся столбцы всегда имеют REF -тип. Конкретный REF -тип зависит от двух факторов:
структурного типа, ассоциированного с типизированной таблицей: REF -тип всегда связан с некоторым структурным типом;
от выбранного способа генерации ссылочных значений; эта информация задается в определении структурного типа и не присутствует в спецификации ссылочного типа.
В спецификации ссылочного типа задается имя структурного типа, на экземпляры которого будут указывать значения ссылочного типа (referenced type ). REF -тип может использоваться в качестве типа атрибута структурного типа, и в этом случае referenced _ type может быть тем же самым, что и определяемый структурный тип. Во все остальных случаях referenced _ type должен являться некоторым существующим структурным типом.
В необязательном разделе указания области действия значений ссылочного типадолжно задаваться имя типизированной таблицы, ассоциированным структурным типом которой является referenced _type REF -типа, в спецификации которого содержится этот раздел. Ассоциированный структурный тип таблицы, на строки которой указывают значения REF -типа, должен быть в точности тем же, что и referenced _type этого REF -типа. Но можно объявить REF -тип, у которого referenced _type является ассоциированным структурным типом подтаблицы, хотя самоссылающийся столбец этой подтаблицы необходимо наследуется от максимальной супертаблицы семейства таблиц.
Если раздел указания области действия значений действительно присутствует, то требуется также указать, нужна ли проверка ссылочных значений.
Если проверка не требуется, то в определяемом столбце можно хранить любое ссылочное значение, независимо от того, является ли оно значением самоссылающегося столбца какой-либо таблицы на строку, которой предположительно указывает ссылка. В этом случае система не гарантирует, что ссылочное значение действительно указывает на строку (но, конечно, это значение должно быть значением правильного типа – REF -типа указанного структурного типа).
Если же указывается потребность в проверке, то каждый раз при сохранении значения в определяемом столбце система обращается к указанной таблице, чтобы убедиться в том, что в ней имеется строка, значение самоссылающегося столбца которой совпадает с сохраняемым ссылочным значением. Кроме того, в этом случае можно также указать ссылочное действие, которое должно выполняться при удалении строки, идентифицируемой ссылочным значением.
Возможными ссылочными действиями являются RESTRICT , CASCADE , SET NULL и NO ACTION . Если ссылочное действие явно не указывается, по умолчанию принимается NO ACTION .
Заметим, что если раздел указания области действия значенийвключается в определение атрибута структурного типа, то соответствующий раздел не может присутствовать среди опций столбца типизированной таблицы, соответствующего данному атрибуту.
Выборка данных из типизированных таблиц
Приведем несколько примеров операций выборки данных из типизированных таблиц, а также операций обновления таких таблиц. Для этого сначала определим структурные типы EMP _ T , PROGRAMMER _ T и DEPT _ T , а также соответствующие типизированные таблицы (упрощенный вариант).
CREATE TYPE EMP_T AS (
EMP_NAME VARCHAR(20),
EMP_BDATE DATE,
EMP_SAL SALARY,
DEPT REF (DEPT) )
INSTANTIABLE
NOT FINAL
REF IS SYSTEM GENERATED
INSTANCE METHOD age ()
RETURNS DECIMAL (3,1)
CREATE TYPE PROGRAMMER_T UNDER EMP_T AS (
PROG_LANG VARCHAR (10) )
INSTANTIABLE
NOT FINAL
CREATE TYPE DEPT_T AS (
DEPT_NO INTEGER,
DEPT_NAME VARCHAR(200),
DEPT_MNG REF (EMP) )
INSTANTIABLE
NOT FINAL
CREATE TABLE EMP OF EMP_T
( REF IS DEPT_ID SYSTEM GENERATED,
DEPT WITH OPTIONS SCOPE DEPT )
CREATE TABLE PROGRAMMER OF PROGRAMMER_T UNDER EMP
CREATE TABLE DEPT OF DEPT_T
( REF IS EMP_ID SYSTEM GENERATED,
DEPT_MNG WITH OPTIONS SCOPE EMP )
Во-первых, заметим, что с типизированными таблицами можно работать как с обычными таблицами. Поэтому, частности, возможен следующий запрос.
Пример 3.1. Найти имена всех служащих, размер заработной платы которых меньше 20000.00.
SELECT EMP_NAME
FROM EMP
WHERE EMP_SAL < 20000.00
В соответствии с семантикой SQL :1999, при выполнении запроса из прим. 3.2 сначала будет произведена выборка имен служащих, удовлетворяющих условию, из таблицы EMP , затем – из таблицы PROGRAMMER , и эти промежуточные результаты будут скомбинированы в окончательный результат путем применения операции объединения ( UNION ).
Но предположим, что нас интересуют только те служащие, получающие зарплату, меньшую 20000.00, которые не являются программистами (пример 3.2). Тогда можно применить формулировку запроса, в которой присутствует спецификация ONLY :
SELECT EMP_NAME
FROM ONLY ( EMP )
WHERE EMP_SAL < 20000.00
Естественно, в запросах к типизированным таблицам можно использовать ссылки.
Пример 3.3. Найти имена и названия отделов всех служащих, размер заработной платы которых меньше 20000.00.
SELECT EMP_NAME, DEPT -> DEPT_NAME
FROM EMP
WHERE EMP_SAL < 20000.00
В SQL :1999 операция “ -> ” называется операцией разыменования , но в обиходе можно считать ее операцией перехода по ссылке (в нашем примере DEPT ссылается на DEPT _ NAME ). Можно неформально трактовать ссылочные значения как указатели на строки типизированных таблиц.
Может показаться неожиданным, что запрос из прим. 3.3 выбирает значения из таблицы DEPT , хотя она даже не упоминается в разделе FROM этого запроса. Дело в том, что выполнение операции разыменования фактически приводит к выполнению соединения таблиц EMP и DEPT , делая “видимым” в запросе столбец DEPT _ NAME .
Конечно, в запросе допускаются многократные переходы по ссылкам, так что можно сформулировать следующий запрос:
Пример 3.4. Найти имена служащих и имена руководителей их отделов для служащих, получающих зарплату, меньшую 20000.00.
SELECT EMP_NAME, DEPT -> DEPT_MNG -> EMP_NAME
FROM EMP
WHERE EMP_SAL < 20000.00
Как показывает следующий пример, в запросах можно использовать вызовы методов над строками, к которым производится переход по ссылке.
Пример 3.5. Найти имя и возраст руководителя отдела 605.
SELECT DEPT_MNG -> EMP_NAME, DEPT_MNG -> age ()
FROM DEPT
WHERE DEPT_NO = 605
Наконец, имеется возможность полностью выбрать экземпляр структурного типа, идентифицируемый ссылочным значением (в SQL :1999 это называется разрешением ссылки – reference resolution ).
Пример 3.6. Получить полные данные о руководителе отдела 605.
SELECT DEREF ( DEPT_MNG )
FROM DEPT
WHERE DEPT_NO = 605
В этом случае результатом запроса будет являться таблица, включающая один столбец структурного типа EMP _ T . Единственным значением этого столбца будет являться экземпляр (значение) этого структурного типа, соответствующий служащему-руководителю отдела 605.
Операции обновления типизированных таблиц выполняются очевидным образом. Операция INSERT вставляет указанные строки в указанную таблицу. Операции DELETE и UPDATE удаляют или модифицируют строки в иерархии таблиц, корнем которой является указанная таблица, если в операции не содержится ONLY . Если же специфицировано ONLY , то удаляются или модифицируются только строки указанной таблицы.
Структура, поведение, наследование
Для некоторых типов данных имеет смысл трактовать объект как именованный набор атрибутов. Этот вид определяемого пользователями типа в терминологии IBM называется структурным типом. Его поддержка появилась в DB 2 UDB Version 5.2 в 1998. Механизм структурных типов с самого начала включал не только возможность определения типов со структурой, но и средства определения иерархий типов и иерархий таблиц. Кроме того, допускалось использование “ссылок” для определения связей между объектами и навигации от одного объекта к другому.
Для определения поведения структурного типа можно было использовать UDF . Однако в DB 2 Version 7 появилась возможность определения методов объектов. Методы очень похожи на UDF в том отношении, что они могут быть написаны на SQL или на внешнем языке, например, на Java или C . Но методы всегда ассоциируются с некоторым структурным типом, и их вызовы производятся в синтаксисе, отличном от синтаксиса вызова UDF .
Любая объектно-реляционная возможность DB 2 может быть использована в традиционном SQL . Чем дальше, тем увереннее можно говорить, что “традиционным” SQL в контексте DB 2 является SQL :1999. В одном приложении может потребоваться всего лишь поддержка LOB , а в другом могут понадобиться структурные типы, методы и наследование. Возможно даже использование объектно-ориентированного моделирования реляционных данных на основе объектных представлений.
Синтаксис оператора создания определяемого пользователем структурного типа очень поход на синтаксис оператора определения таблицы – указываются имя типа, имена его атрибутов и типы данных этих атрибутов. При создании подтипов структурного типа эти подтипы автоматически наследуют атрибуты супертипа.
Типизированные представления
Наряду с типизированными базовыми таблицами в SQL :1999 поддерживаются типизированные представления, иначе называемые представлениями, на которые можно ссылаться ( referenceable views ). Иногда такие представления также называют объектными представлениями, поскольку данные, видимые через представление, соответствуют строкам типизированных таблиц, поведение которых во многом похоже на поведение объектов в объектно-ориентированных системах. Между типизированными базовыми таблицами и типизированными представлениями имеется большое сходство, но есть и несколько отличий, связанных с врожденными различиями базовых таблиц и представлений.
В SQL в связи с объектными представлениями вводится ряд терминов – суперпредставление, подпредставление, непосредственное суперпредставление, непосредственное подпредставление, собственное суперпредставление и собственное подпредставление. Смысл этих терминов полностью аналогичен смыслу соответствующих терминов для типизированных базовых таблиц. Термин семейство подтаблиц применяется по отношению и типизированных таблиц, и типизированных представлений.
При определении типизированного представления указывается имя существующего структурного типа. Как и в определении обычных представлений, специфицируется выражение запроса. В случае типизированных представлений это выражение запроса должно основываться на единственной типизированной таблице (базовой таблице или представлении). Эта типизированная таблица должна быть ассоциирована с тем же структурным типом, что и определяемое представление. Такую таблицу называют базисной таблицей представления.
Типизированное представление можно определить как подпредставление другого типизированного представления. В этом случае структурный тип, ассоциированный с определяемым представлением, должен являться непосредственным подтипом структурного типа, ассоциированного со специфицируемым в разделе UNDER суперпредставлением. Базисная таблица определяемого представления должна являться собственной подтаблицей или собственным подпредставлением – не обязательно непосредственным – базисной таблицы непосредственного суперпредставления определяемого представления.
В определение типизированного представления может входить один или несколько элементов, задающих область действия ссылочных значений столбцов REF -типов. Если представление определяется как подпредставление другого типизированного представления, то в его определении не должна содержаться спецификация самоссылающегося столбца. Если определяется максимальное суперпредставление, то эта спецификация может, но не обязана присутствовать. Если спецификация присутствует, то она может содержать только генерируемые пользователями или порождаемые ссылочные значения (из этого следует, что нельзя определить типизированные представления, в ассоциированном структурном типе которого присутствует спецификация системно-генерируемых ссылочных значений) .
Типизированные таблицы
В предыдущем подразделе уже упоминалась возможность определения типизированных таблиц, основанных на некотором структурном типе. Здесь мы приведем и поясним понятие иерархии типизированных таблиц и связь этой иерархии с иерархией структурных типов, а также обсудим соотношение понятие строки типизированной таблицы с понятием объекта в ООБД.
Типы коллекций
Начиная с SQL :1999, в языке поддерживается возможность использования типов данных, значения которых являются коллекциями значений некоторых других типов. Обычно под термином коллекция понимается одно из следующих образований: массив, список, множество и мультимножество. В варианте SQL :1999, принятом в 1999 г., специфицированы только типы массивов. Любой возможный тип массива получается путем использования конструктора типов ARRAY . При определении столбца, значения которого должны принадлежать некоторому типу массива, используется конструкция
dt ARRAY [ mc
] , где dt специфицируетнекоторый допустимый в SQL тип данных (отличный от типа массива), а mc является литералом некоторого точного числового типа с нулевой длиной шкалы и определяет максимальное число элементов в значении типа массива (в терминологии SQL :1999 это значение называется максимальной кардинальностью массива). Тем самым, в текущей версии стандарта SQL :1999 не поддерживаются многомерные массивы и массивы массивов.
Элементам каждого значения типа массива соответствует их порядковый номер, называемый индексом. Значение индекса всегда должно принадлежать отрезку [1, mc ]. Значениями типа массива dt ARRAY [ mc ] являются все те массивы, состоящие из элементов типа dt , максимальное значение индекса которых cs не превосходит значения mc . При сохранении в базе данных значение типа массива занимает столько памяти, сколько требуется для сохранения cs элементов. Обеспечивается доступ к элементам массива по их индексам. В частности, можно объявить столбец типа INTEGER ARRAY [10] и при вставке строки в соответствующую таблицу задать значение только пятого элемента массива. Тогда в строку будет занесен массив из пяти элементов, причем первые четыре элемента будут содержать неопределенное значение (NULL ).
Основными операциями над массивами являются выборка значения элемента массива по его индексу, изменение некоторого элемента массива или массива целиком и конкатенация (сцепление) двух массивов. Кроме того, для любого значения типа массива можно узнать значение его cs .
поддерживаются две разновидности типов
В Oracle 8 поддерживаются две разновидности типов коллекций: табличные типы (table types) и типы массивов. Значениями каждого типа коллекции являются коллекции (таблицы или массивы) элементов одного и того же типы (типа элемента). Тип элемента может быть встроенным или объектным типом, но не типом коллекции. Поскольку табличный тип является оригинальным изобретением компании Oracle, остановимся на нем немного подробнее. Табличный тип создается конструкцией следующего вида:
CREATE TYPE < имя типа > AS TABLE OF < тип элемента >;
Например, при наличии определения объектного типа EMP _ T можно было бы определить табличный тип DEPENDENTS _ T следующим образом:
CREATE TYPE DEPENDENTS_T AS TABLE OF EMP_T;
После этого можно определить таблицу BOSSES, содержащую столбец, значениями которого являются таблицы, которые содержат данные о подчиненных служащего:
CREATE TABLE BOSSES
( boss EMP_T,
dependentsEMP_T,
PRIMARY KEY ( boss.EMP_NO ) )
Nested TABLE DEPENDENTS STORE AS DEPENDENTS_TAB;
В результате выполнения этой операции в базе данных будут созданы две таблицы – таблица верхнего уровня BOSSES и вложенная таблица DEPENDENTS _ TAB , содержащая все строчные объекты, которые соответствуют сотрудникам-подчиненным. Конечно, если в таблице верхнего уровня имелось бы несколько столбцов табличного типа, то для каждого из этих столбцов потребовался бы свой раздел Nested TABLE . П родемонстрируем возможность выборки из таблицы с вложенной подтаблицей на примере.
Пример 3.7. Выбрать из таблицы BOSSES все пары “начальник-подчиненный”.
SELECT B.boss.EMP_NO, D.EMP_NO
FROM BOSSES B, TABLE ( B.dependents) D
Должно быть понятно, что этот запрос в сокращенной форме выражает естественное соединение таблиц BOSSES и DEPENDENTS _ TAB . Поэтому в результате не появятся данные о служащих, данные о которых включены в таблицу BOSSES и которые не имеют подчиненных. Чтобы получить данные обо всех сотрудниках, данные о которых включены в таблицу BOSSES , в синтаксисе SQL Oracle 8 требуется задать следующий запрос:
SELECT B.boss.EMP_NO, D.EMP_NO
FROM BOSSES B, TABLE ( B.dependents ) (+) D
Этот запрос соответствует требованию правого внешнего естественного соединения. Во встроенном SQL Oracle 8 имеются и другие способы доступа к вложенным таблицам, которые мы не будем обсуждать в этой статье.
Вторая разновидность типов коллекций в Oracle 8 называется VARRAY , что вполне соответствует стандарту SQL :1999 и означает “массив переменного размера” (varying -length array ). При определении типа массива указываются имя типа, тип элементов и максимальное число элементов, которые может содержать значение определяемого типа. В отличие от значений табличного типа, для элементов значений типа массива поддерживается порядок.
Как и в случае с множествами (и мультимножествами) в IUS, на уровне прямого SQL в Oracle можно работать только с массивами целиком. Однако существует возможность привести в запросе (или другом операторе SQL) тип массива к табличному типу.
Точка зрения компании IBM относительно ОРСУБД
Традиционные возможности языка SQL , связанные с типами данных и поиском, недостаточны для нового поколения мультимедийных приложений баз данных. Также понятно, что требования таких приложений настолько различны, что не могут быть удовлетворены любым набором предопределенных расширений языка. Требуются средства определения пользователями новых типов данных и функций над ними.
Другим требованием современных приложений баз данных является возможность хранения правил, делающих данные более активными и позволяющих системе баз данных автоматически выполнять проверки корректности данных и автоматизировать многие бизнес-процедуры. Активизация данных дает возможность приложениям совместно использовать не только сами данные, но и поведение данных.
Обе указанные возможности позволяют повысить ценность хранимых данных за счет расширения их семантического содержимого. Тенденция к повышению роли семантического содержимого хранимых данных является наиболее важной в современном управлении базами данных. В соответствии с этой тенденцией реляционные системы баз данных расширяются в двух направлениях: (1) добавлении “объектной инфраструктуры” к самой системе баз данных в виде поддержки определяемых пользователями типов данных, функций и правил; (2) построении поверх этой инфраструктуры “реляционных расширителей”, которые поддерживают специализированные приложения, такие как выборка изображений, развитый текстовый поиск, географические приложения. Система, которая обеспечивает объектную инфраструктуру и набор реляционных расширителей, называется “объектно-реляционной”.
Тринадцать предложений
Во Втором манифесте выдвигались три группы детальных предложений, которым, по мнению авторов манифеста, должны были следовать удачные образцы систем баз данных третьего поколения 90-х годов. Предложения первой группы следуют из принципа 1 и уточняют требования к управлению объектами и правилами. Во второй группе содержится набор предложений, являющихся следствием того, что системы третьего поколения должны включать в себя системы второго поколения. Наконец, в третью группу сведены предложения, исходящие из требования открытости систем третьего поколения.
Второй манифест
Авторы Второго манифеста относят к первому поколению систем баз данных предшествовавшие РСУБД иерархические и сетевые системы, а существовавшие во время написания манифеста реляционные системы – ко второму поколению. В документе рассматриваются характеристики, которыми должны обладать менеджеры баз данных следующего, уже третьего поколения. Требования состоят из трех основных принципов и тринадцати детальных предложений.
и иерархические системы баз данных,
Сетевые и иерархические системы баз данных, широко распространенные в 70-е годы, получили название систем баз данных первого поколения. Действительно, это были первые системы, предлагавшие развитую функциональность СУБД в рамках единой системы, с языками определения и манипулирования данными для наборов записей. Типичными представителями первого поколения являются сетевые системы, основанные на предложениях CODASYL , и иерархическая СУБД IMS .
В 80-е годы системы первого поколения были существенно потеснены семейством реляционных СУБД, называемых в манифесте системами баз данных второго поколения. Их появление стало важным шагом вперед для многих приложений, так как в этих системах использовались непроцедурные языки манипулирования данными и предусматривалась значительная степень независимости данных. Типичными представителями систем второго поколения во время написания Второго манифеста
являлись DB 2, INGRES , NON -STOP SQL , ORACLE и Rdb /VMS 53.
Однако системы второго поколения были сфокусированы на приложениях обработки бизнес-данных и не являлись адекватными решениями для более широкого класса приложений. Системы автоматизации проектирования (САПР), системы CASE и гипертекстовые приложения часто выделяются как примеры, в которых можно было бы эффективно использовать различные СУБД, обладающие специализированными возможностями. Например, для обеспечения работоспособности издательской системы необходимо хранить элементов данных, встречаемых в гипертекстовых средах. Поддержка таких элементов данных системами второго поколения обычно сопряжена с немалыми трудностями.
Но в действительности системы второго поколения не особо хороши и для поддержки большинства бизнес-приложений. Например, для страхового приложения, обрабатывающего требования о выплатах, требуются традиционные типы данных, такие как имя человека и размер причитающейся ему страховой выплаты, но желательно также хранить и образы фотографий события, к которому относится требование о выплате, и факсимиле оригинального рукописного требования о выплате.
Подобные элементы данных неудобно хранить в СУБД второго поколения. Более того, вся информация, имеющая отношение к определенному требованию о выплате, объединяется в папку, содержащую традиционные данные, образы и, возможно, процедурные данные. Структура папки часто бывает настолько сложной, что в сравнении с ней элементы данных и агрегированные данные САПР и CASE -систем кажутся довольно простыми.
Большинство современных поставщиков СУБД работают над значительным расширением функций своих СУБД второго поколения. Они единодушны в отношении желаемых возможностей систем следующего, третьего поколения. Во Втором манифесте авторы предлагают три основных принципа, которыми, по их мнению, следует руководствоваться при создании систем третьего поколения. Кроме этого, приводятся 13 предложений, в которых требования к новым системам обсуждаются более детально. Авторы полагают целесообразным сопоставить их работу с Манифестом систем объектно-ориентированных баз данных, в котором предлагаются другие наборы принципов.
Заключение к разделу
Если обратиться к истории, то обнаружится, что попытки расширения функциональности СУБД, изначально основанных на реляционном подходе, предпринимались уже на ранних стадиях разработки таких систем. Классическими примерами являются проекты System R (IBM ), где пытались обеспечить возможности работы со сложными объектами путем расширения SQL [27], и Ingres (университет Беркли), где Майкл Стоунбрейкер предлагал механизм определения пользовательских типов данных на основе представлений и хранимых процедур [28]. Однако новый толчок к расширению SQL -ориентированных СУБД объектными свойствами был получен со стороны объектного мира после публикации Первого манифеста.
В ответном Втором манифесте индустрия развитых СУБД утверждала, что имеются реальные возможности добиться желаемой функциональности без коренной ломки традиционной технологии. Идеи Второго манифеста были воплощены в жизнь в нескольких ведущих SQL -продуктах, и использование объектных расширений позволило самим поставщикам обеспечить ряд законченных функциональных расширений своих систем. Однако ожидания большого спроса на сами инструменты объектных расширений со стороны пользователей не оправдались. Некоторые известные специалисты из области баз данных считают, что для этого еще не пришло время.
Развитие объектно-реляционного подхода отразилось в соответствующем развитии языка SQL . Гигантский стандарт SQL :1999 позволяет хотя бы сопоставлять отдельные реализации, хотя ни одна компания полностью его не поддерживает.
Заключение подраздела
Разработчики DB 2 UDB собирались включить в систему и средства работы с типами коллекций, однако, насколько это известно автору, пока это не произошло. Вообще, следует заметить, что в настоящее время IBM и Oracle предлагают объектно-реляционные расширения, обеспечивающие практически одинаковую функциональность. Системы Informix , став частью IBM , теперь подчиняются общей стратегии этой компании. Помимо прочего, эта стратегия включает отказ от дальнейшего развития собственной линии объектно-реляционных расширений Informix .
Заключение Второго Манифеста
Авторы Манифеста баз данных следующего поколения во многом согласны с энтузиастами ООБД. Среди общих тем выделяются выгодность использования богатой системы типов, функций, наследования и инкапсуляции. Однако во многих областях позиции прямо противоположны. Во-первых, Манифест объектно-ориентированных баз данных слишком узко сфокусирован на вопросах управления объектами. Авторы Второго манифеста обращаются к более широкому кругу вопросов, включающих поддержку управления данными, правилами и объектами на основе полного набора инструментов при наличии интеграции СУБД и языка запросов в многоязычную среду. Предлагаемые многими энтузиастами ООБД одноязычные системы, не поддерживающие SQL , привлекательны лишь для довольно узкого рынка.
Во-вторых, представляется, что доступ к СУБД должен осуществляться при помощи языка запросов, и история подтверждают правильность такой точки зрения. Следует избегать физической навигации, выполняемой программами пользователей или происходящей внутри функций. В-третьих, необходимо всячески поощрять использование автоматических наборов, так как они предоставляют массу преимуществ по сравнению с явно поддерживаемыми наборами. В-четвертых, свойство стабильности данных может быть добавлено ко многим языкам программирования. Поскольку не существует языка программирования, аналогичного эсперанто, этого следует достигать путем изменения компилятора и написания специфичной для языка системы времени выполнения, взаимодействующей с единой СУБД. Таким образом, языки программирования с поддержкой стабильных данных мало связаны с моделями данных. В-пятых, уникальные идентификаторы должны задаваться либо пользователем, либо системой (здесь наличествует противоречие с одним из принципов Первого манифеста).
Основной вопрос, по которому авторы Второго манифеста расходились во мнениях с большей частью сообщества ООБД, – это возможность естественной эволюции современных реляционных систем к системам, поддерживающим возможности, обсуждаемые в данной работе.
Авторы данного манифеста верили в такую возможность. Уже в то время продукты основных поставщиков реляционных систем удовлетворяли принципам 1, 2 и 3 и обеспечивали хорошую поддержку предложений 1.3, 1.4, 1.5, 2.1, 2.3, 2.4, 3.1, 3.3 и 3.4. Для превращения в СУБД третьего поколения в эти продукты оставалось добавить наследование и дополнительные конструкторы типов и внедрить языки программирования с поддержкой стабильных данных. Существовали прототипы систем, указывающие пути включения и этих средств.
С другой стороны, современные (в то время) системы, провозглашаемые объектно-ориентированными, обычно не соответствуют провозглашаемым во Втором манифесте принципам и поддерживают лишь предложения 1.1 (частично), 1.2, 1.3 и 3.2. Для превращения в подлинные СУБД третьего поколения таким системам не хватает языка запросов и оптимизатора запросов, системы правил, поддержки SQL в архитектуре клиент-сервер, поддержки представлений и языков программирования со стабильными данными. Кроме того, в них должны быть отменены любые жесткие требования наличия уникальных идентификаторов и прекращено поощрение навигации. Более того, в них необходимо построить языки четвертого поколения, внедрить поддержку распределенных баз данных и осуществить настройку системы для эффективного управления данными.
Конечно, воплотить предложения манифеста непросто – придется столкнуться со многими проблемами. Создание языка с поддержкой стабильных данных для разнообразных языков программирования – труднейшая задача. Другую проблему представляет включение в такие языки приемлемых конструкций языка запросов. Далее, логическое и физическое проектирование баз данных для современных реляционных систем считается непростой задачей, а с внедрением более богатой системы типов и правил она еще более усложнится. Для помощи пользователю здесь потребуются методологии и инструменты проектирования баз данных. Серьезную трудность представляет оптимизация выполнения правил. Кроме того, для успеха новых технологий крайне важна визуализация и отладка ориентированных на правила приложений.