Расширенные ОРБД
К расширенным ОРБД относится СУБД Informix Universal Server [41,42]. С помощью этой разновидности ОРБД решают две группы задач: 1) хранение в БД данных большого объема; 2) трансформация реляционной модели (собственно БД) в объектно-реляционную модель данных.
Обсудим состояние решения этих задач.
Задача 1. Первоначально графические базы данных создавались так: отдельно формировались графические файлы, а в столбцах СУБД были лишь ссылки на эти файлы. Это требовало от программиста знания не только БД, но и системы файлов. В связи с этим в состав СУБД были первоначально введены "простые большие объекты" (рис. 8.6) TEXT и BYTE с объемом до 1 Гбайт.
Вскоре выяснилось, что и такая размерность поля порой недостаточна, и были созданы интеллектуальные большие объекты Binary Large Object (BLOB) и CLOB размером до 4 Тбайт. Работа с такими объектами возможна только "по частям", для чего пришлось создать специальные дополнительные технологии.
Рис. 8.6. Большие объекты
Задача 2. Идею расширения (системы данных) удобно иллюстрировать на примере [41] программы (среда Delphi, язык Object Pascal):
unit polimor_;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForml = class(TForm)
Editl: TEdit;
Edit2: TEdit;
GroupBoxI: TGroupBox;
RadioButtonl: TRadioButton;
RadioButton2: TRadioButton;
Label 1: TLabel;
Label2: TLabel;
Button1:TButton;
Button2:TButton;
procedure Button 1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations}
public
{Public declarations}
end;
type
TPerson=class
fname:string;{имя}
constructor Create(name:string);
function info:string; virtual;
end;
TStud=class(TPerson)
fgrrinteger; {номер группы} constructor Create(name:string;gr:integer); function infoistring; override;
end;
TProf=class(TPerson)
fdep:string; {название кафедры}
constructor Create(name:string;dep:string);
function info:string; override;
end;
const
SZL=10; // размер списка
var
Forml: TFormt;
List: array[1 ..SZL] of TPerson; // список
n:integer; // кол-во людей в списке
implementation
{$R*.DFM}
constructor TPerson.Create(name:string);
begin
fname:=name;
end;
constructor TStud. Create( name :string ;gr: integer);
begin
inherited create(name);
fgr:=gr;
end;
constructor TProf.create(name:string; dep:string);
begin
inherited create(name);
fdep:=dep;
end;
function TPerson.lnfo:string;
begin
result:=fname;
end;
function TStud.lnfo:string;
begin
result:=fname+'гр .' +lntT oStr(fgr);
end;
function TProf.lnfo:string;
begin
result:=fname+'каф .'+fdep;
end;
procedure TForml .Button1Click(Sender: TObject);
begin
if n<=SZL then begin
if Radiobutton 1 .Checked
then // создадим объект TStud
List[n]:=TStud.Create(Edit1.Text,StrTolnt(Edit2.Text))
else
List[n]:=TProf.Create(Edit1.Text,Edit2.Text);
n:=n+1;
end
else ShowMessage('Список заполнен!');
end;
procedure TForml .Button2Click(Sender: TObject);
var
i: integer;
st: string;
begin
for i:=1 toSZL do
if list[i] <> NIL then st:=st+list[i].info+# 13;
ShowMessage('Список'+# 13+st);
end;
end.
Из нее видно, что классы "Студент" (TStud) и "Профессор" (TProi) являются производными от класса "Личность" (TPerson). В качестве
методов доступа к ним выступают функции TStud.Info.string, TProf.Info.string и TPerson.lnfo.string соответственно.
Язык программирования Object Pascal редко используется для формирования объектно-ориентированной модели базы данных. Чаще для этих целей применяют языки С++ и SQL.
Покажем на примерах использование языка SQL3 в СУБД Informix Universal Server.
В SQL3 используются те же типы данных, что и в SQL2. Однако SQL3 оперирует не таблицами, как SQL2, а объектами. В качестве таких объектов выступают новые (абстрактные) типы данных и система таблиц, образующих иерархию.
А. Абстрактные типы данных (рис. 8.7). Абстрактные типы данных, получившие в последнее время название "типы данных, определяемые пользователем" [2], – типы, задающие характеристики [3], но не реализации, наследуемые подтипом. Они непосредственно не порождают экземпляров.
В иерархии типов участвуют (рис. 8.7) ROW (неименованные строки), ROW TYPE (именованные строки), SET (неупорядоченный набор одного типа без повторения данных), MULTISET (то же, что и SET, с возможностью повторения данных), LIST (упорядоченный набор неуникальных данных одного типа, фактически – одномерный массив). Разнородные структуры добавляют каждый раз по одной строке к предыдущей строке, тогда как однородные структуры могут добавлять по нескольку строк к каждой предыдущей строке.
Рис. 8.7. Новые абстрактные типы данных
Использование новых типов рассмотрим на системе таблиц, показанных на рис. 8.8. Иерархия требует множественного наследования. Поскольку оно не реализовано в рамках СУБД Informix Universal Server, ограничимся рассмотрением части иерархии, обведенной на рис. 8.8 пунктиром.
Рис. 8.8. Иерархия абстрактных типов данных и таблиц
Речь должна пойти о построении типов данных, их заполнении и обновлении. Первоначально покажем использование типа данных ROW для элементов иерархии "Деканат", "Группа", "Студент", "Кафедра". Для иллюстрации в каждом структурном элементе используем только по два поля, а названия таблиц и полей выполним на русском языке.
CREATE ROW TABLE Деканат(
Шифр_деканата integer,
Название varchar( 15),
Группа ROW(
Шифр_группы varchar(8),
Название_группы varchar(5),
Студент ROW( Шифр_студента varchar(8),
Фамилия varchar( 15)),
Кафедра ROW(
Шифр_кафедры integer,
Название_кафедры varchar{50))
);
Выборка данных осуществляется следующим образом.
SELECT шифр_деканата, группа.название_группы, группа.студент.фамилия
FROM Деканат
WHERE группа.название_группы='И5';
Заполнение (вставка) в такую структуру проводится так:
INSERT INTO Деканат
VALUES (1/ПТИО',
ROW('И-99', 'И4',
ROW('И-99/15', 'Петров')),
ROW(1, 'ИиУС'));
В типе данных ROW структура строки (записи) каждый раз должна определяться отдельно. Это не позволяет использовать структуру ROW многократно.
Такую возможность предоставляет именованная запись ROW TYPE. В этом случае Назад структура "Деканат" задается иначе.
Первоначально формируются именованные записи.
CREATE ROW TYPE Студент_TYРЕ(
Шифр_студента varchar(8),
Фамилия varchar( 15)
);
CREATE ROW TYPE Гpyппa_TYPE(
Шифр_группы varchar(8),
Название_группы varchar(5),
Студент Студент_ТУРЕ
);
CREATE ROW TYPE Кафедра_TYPE(
Шифр_кафедры integer,
Название_кафедры varchar(50)
);
Из именованных записей составляется структура "Деканат"
CREATE ROW TABLE Деканат(
Шифр_деканата integer,
Название varchar( 15),
Г руппа Гpyппa_TYPE,
Кафедра Кафедра TYPE
);
При этом сформируется таблица с нелинейной структурой (табл. 8.1).
Таблица 8.1
Сформированная таблица "Учебный процесс"
Шифр деканата |
Название деканата |
Группа |
Студенты |
Кафедра |
|||
Шифр группы |
Название группы |
Шифр студента |
Фамилия |
Шифр кафедры |
Название кафедры |
||
1 |
ПТиО |
И-99 |
И4 |
И-99/12 |
Петров |
1 |
ИиУС |
1 |
ПТиО |
И-99 |
И4 |
И-99/11 |
Смирнов |
1 |
ИиУС |
... |
... |
... |
... |
... |
... |
... |
... |
Можно таблицу построить и другим способом.
CREATE ROW TYPE Деканат_ТУРЕ(
Шифр_деканата integer,
Название varchar( 15),
Группа Гpynna_TYPE,
Кафедра Кафедра_ТУРЕ
);
и
CREATE TABLE Деканат OF TYPE Деканат_ТУРЕ;
Последняя таблица получила название типизированной. Заметим, что при вставке в тип ROW проблем не возникает:
INSERT INTO Деканат
VALUES (','ПТИО',
ROW('И-99', 'И4',
ROW('И-99/15',
'Петров')::Студент_ТУРЕ)::Группа_Туре,
ROW( 1, 'ИиУС')::Кафедра_ТУРЕ);
где знак :: обозначает перевод записи в элемент ROW.
Операторы заполнения ROW TYPE сложнее, чем ROW, и требуют написания хранимых процедур или функций. Например, список групп в деканате формируется следующим образом:
CREATE FUNCTION Список_групп(Деканат.ГpyппaTYPE)
RETURNS(varchar(8), varchar(5)) AS
RETURN(группа.Шифр_группы, Группа.Название_группы)
END FUNCTION;
Рис. 8.9. Иерархия абстрактных типов данных (наследование)
Таблицу "Преподаватель" на рис. 8.8 временно заменим на таблицу "Работающий", подразумевая, что преподаватель одновременно и преподаватель, и (научный) сотрудник (рис. 8.9).
CREATE ROW TYPE адрес_ТУРЕ(
Город varchar(15),
Улица varchar(15),
Дом integer,
Корпус integer,
Квартира integer
);
CREATE ROW TYPE Работающий_ТУРЕ(
Шифр_работающего integer,
Фамилия varchar( 15),
Адрес адрес_ТУРЕ
);
В составе "Работающий" имеются подчиненные ему элементы "Преподаватель" и "Сотрудник". Тогда иерархия подчинения (наследования) типов данных формируется так:
CREATE ROW TYPE Преподаватель_ТУРЕ(
Дисциплина varchar(20),
Вид_занятий varchar(10),
UNDER Работающий TYPE;
CREATE ROW TYPE Сотрудник_ΤΥΡΕ(
Шифр_работы varchar(5),
Название работы varchar(40),
UNDER Работающий_TYРЕ;
Тогда типизированные таблицы имеют вид:
CREATE TABLE Преподаватель OF TYPE Преподаватель_ТУРЕ;
CREATE TABLE Сотрудник OF TYPE Сотрудник_ТУРЕ;
Два последних определения могут включать и внешние ключи.
Фактически сформирована система таблиц. Она отличается тем, что заполнение таблиц идет автономно. Если заполняются поля в таблице "Сотрудник", то одноименные поля в таблице "Работающий" не заполняются.
Б. Иерархия таблиц. Указанное заполнение порой неудобно и потому используют наследование не абстрактных типов данных, а таблиц, которые связывают так:
CREATE TABLE Преподаватель
OF TYPE Преподаватель_ТУРЕ
UNDER Работающий;
CREATE TABLE Сотрудник
OF TYPE Сотрудник_ТУРЕ
UNDER Работающий;
В этом случае таблицы становятся вложенными (рис. 8.10).
Если создать запрос
SELECT * FROM Работающий;
то будут выданы поля как объекта "Работающий", так и объектов "Преподаватель" и "Сотрудник".
Для получения данных только из определенной таблицы (например, "Сотрудник") необходимо создать запрос
SELECT * FROM ONLY(Сотрудник);
Аналогично и с процедурами обновления
Рис. 8.10. Пример вложенной таблицы
DELETE FROM ONLY(Сотрудник)
WHERE Шифр_работы=254;
До сих пор использовались (см. рис. 8.6) разнородные структуры. Однако таблицы могут быть пополнены и однородными структурами (коллекциями).
Добавим к таблицам "Сотрудник" и "Преподаватель" коллекции:
а) участие сотрудника в научных темах:
ALTER TABLE Сотрудник
ADD Проект SET (integer);
б) учебные пособия преподавателя:
ALTER TABLE Преподаватель
ADD Пособия MULTISET (ROW(
Название varchar(30),
Год_издания integer)
);
Заметим, что MULTISET состоит из наборов ROW.
Тогда таблица "Преподаватель" получает новый вид (табл. 8.2).
Таблица 8.2
Новая таблица "Преподаватель"
Шифр работающего |
Фамилия |
Шифр предмета |
Вид занятия |
Адрес |
Пособия |
|||||
Город |
Улица |
Дом |
Корпус |
Квартира |
Название |
Год издания |
||||
28 |
Петров |
1 |
Лекции |
СПб |
Кима |
21 |
2 |
321 |
А Б В |
1999 1998 1995 |
Отметим также, что коллекция – понятие гибкое. Она может быть полем записи и в то же время записи могут играть роль элементов коллекции.
Запросы к коллекциям могут быть составлены лишь в простейших случаях. Запрос на выборку для таблицы "Преподаватель" имеет вид
SELECT шифр_работающего, фамилия,
Пособия.Название
FROM Преподаватель WHERE 1999 IN (Пособия);
Вставка может осуществляться таким оператором
INSERT INTO Преподаватель
VALUES (', 'Иванов', 1, 'преподаватель',
ROW('CПб', 'Московский', 137, 2, 118),
ROW('Информатика', 'лекция'),
“MULTISET{ROW('A1',1996),
ROW('AZ,1997),
ROW('A4',1997)}”);
Следует отметить, что в СУБД Informix Universal Server введен новый тип переменной COLLECTION, в которой в процессе работы программы (хранимой процедуры) могут храниться значения данных.
Для более сложных запросов требуется использовать хранимые процедуры, возможно, с циклами.
С помощью хранимых процедур формируются и необходимые дополнительные методы, поскольку в СУБД Informix Universal Server нет механизма превращения хранимых процедур в методы. Таким образом, язык SQL3 обладает значительно большими возможностями по сравнению с языком SQL2.
В то же время разработчиков БД, видимо, настораживает более сложная структура объектов и, главное, методов. Кроме того, SQL3 характеризуется неполнотой операторов: часть операторов разработчику приходится создавать самому в рамках хранимых процедур, для чего необходимо хорошо знать язык SQL2.
Названные обстоятельства и инерционность привычного, широко распространенного реляционного мышления объясняют, по всей видимости, тот факт, что расширенные ОРБД не нашли пока масштабного применения.
Вместе с тем широкое распространение получила гибридная разновидность ОРБД, являющаяся серьезным усовершенствованием реляционных БД.
Расширенные ОРБД – серьезный шаг в направлении объектно- ориентированных баз данных. Сфера применения таких ОРБД будет, по мнению авторов, расти. Они формируют средства как для революционного перехода к ООБД, так и для постепенного, эволюционного движения в будущее баз данных.
Чтобы понять перспективы развития ОРБД, следует оцепить их достоинства и недостатки
К достоинствам следует отнести [2]:
• устранение ряда недостатков реляционных БД (см. § 8.1);
• повторное использование компонентов;
• использование накопленных знаний по реляционным БД.
К недостаткам ОРБД возможно отнести:
• усложнение структуры БД и частичную утрату простой обозримости результатов, как в реляционных БД;
• сложность построения абстрактных типов данных и методов, связывающих типы в иерархию;
• менее широкий набор типов связей, определяемых языком программирования SQL, чем в объектно-ориентированных БД;
• менее продуманный, отлаженный и стандартизованный набор типов данных, чем в ООБД.
ОРБД, по-видимому, будут существовать еще достаточно долго, чему есть по меньшей мере два объяснения.
1. Быстрое накопление с помощью ОРБД опыта, который можно использовать при создании ООСУБД.
2. Необходимость иметь средства для постепенного эволюционного "перевода" многочисленных реляционных БД в разряд ООБД, за которыми, видимо, будущее.