|
|
|||||||||||||||||||||||||||||
|
Объекты в Oracle - это очень простоВладимир Пржиялковский
ОглавлениеВведениеВ версии 8 в Oracle появилась возможность хранения неатомарных (нескалярных) значений в поле таблицы, а именно объекта в смысле объектного подхода (в рамках так называемой "объектно-реляционной модели" Oracle). Некоторые существенные пробелы этой первой реализации были устранены в версии 9. Примеры ниже используют возможности версии 9.2. Сразу надо предостеречь от преувеличений достоинств объектного подхода в базах данных вообще. Действительно, неискушенный читатель некоторых руководств или рекламных материалов быстро впадет в недоумение: зачем же такие маститые разработчики СУБД, как фирмы IBM, Informix или Oracle так долго занимались табличной организацией данных, когда все это время рядом существовала более совершенная, удобная и т. д. объектная, первая реализация которой фирмой Xerox известна с 1980 года? Непредвзятый ответ состоит в том, что ни табличная организация (часто вольно называемая "реляционной" применительно к конкретным СУБД), ни объектная не являются универсально "хорошими", и что имеются свои достоинства и недостатки у одной и у другой. Некоторые соображения относительно областей применения обоих подходов к хранению данных можно найти в статье "Что объектам здорово, то реляциям смерть, и наоборот, и еще пол-оборота". В целом объектная реализация в Oracle традиционна для объектного подхода вообще. В основе лежит понятие объекта как совокупности свойств (атрибутов), причем действия с объектом регламентируются формулируемым набором методов (процедур или функций). Тип объекта задается сохраняемым в БД объектом TYPE. Хранимые объектыПростой примерРассмотрим схему БД, где хранятся данные о сотрудниках и отделах. Будем работать в схеме SCOTT, из которой на время нужно удалить таблицы EMP и DEPT (позже мы их восстановим). Предположим, что и те, и другие имеют адреса: сотрудники - домашний, а отделы - юридический. Адрес имеет несколько полей (например, "индекс", "район", "населенный пункт", "место"). В традиционной табличной реализации есть два способа промоделировать наличие адреса: - включить одинаковые группы полей в таблицы сотрудников и отделов; Первое решение неудобно тем, что адрес теряет свою идентичность: неудобно, например, сравнивать адреса, особенно в разных таблицах. Второе решение искусственно, если только не считать адреса самостоятельными объектами моделирования. Объектные возможности последних версий Oracle дают возможность более приемлемой альтернативы. Для описания адреса создадим тип (здесь и далее предполагается использование в качестве рабочего инструмента SQL*Plus): CREATE TYPE address_typ AS OBJECT ( Воспользуемся этим типом для описания сотрудников и отделов: CREATE TABLE dept ( CREATE TABLE emp ( Проверим описания созданных объектов: DESCRIBE address_typ Пример заведения сотрудников и отделов: INSERT INTO dept VALUES ( INSERT INTO emp VALUES ( Здесь выражение ADDRESS_TYP('123333', 'Boston 567... ') означает обращение к конструктору объекта, то есть к функции, автоматически создаваемой СУБД при заведении нового типа для возможности создавать новые объекты этого типа с нужными значениями атрибутов. Понятие конструктора общепринято в объектном подходе. В приведенных предложениях INSERT простановку адреса можно оформить чуть иначе, добавив, в соответствии с духом объектного подхода, ключевое слово NEW перед обращением к конструктору: INSERT INTO emp VALUES ( Проверка: COLUMN dname FORMAT A20 SELECT * FROM dept; SELECT * FROM emp; Другие примеры: SELECT ename, home FROM emp; SELECT e.ename, d.dname FROM emp e, dept d WHERE e.home = d.addr; SELECT e.ename, e.home.zip FROM emp e; UPDATE emp UPDATE emp e SET e.home.zip = '123458' WHERE ename = 'Allen'; Создание таблицы объектовЕсли адрес интересует нас как самостоятельная сущность, а не атрибут прочих сущностей, созданный для адреса тип можно использовать для создания таблиц объектов: CREATE TABLE addr_list1 OF address_typ; CREATE TABLE addr_list2 OF address_typ; Таблицы объектов в Oracle было бы точнее называть списками объектов, так как это всегда таблицы ровно из одного столбца объектного типа. Заполнение данными происходит как и ранее: INSERT INTO addr_list1 VALUES или INSERT INTO addr_list1 VALUES INSERT INTO addr_list2 VALUES Просмотр: COLUMN location FORMAT A30 SELECT * FROM addr_list1; SELECT VALUE(a) FROM addr_list1 a; SELECT e.ename, e.home (Функция VALUE специально придумана для возвращения значений объектов, а не атрибутов объектов по отдельности). Ссылки на объектОбъекты, заведенные в объектных таблицах, имеют одно преимущество перед объектами, указанными как атрибут строки: на них можно ссылаться. Ссылка есть уникальный внутренний идентификатор объекта, и получить его можно с помощью функции REF: COLUMN ref FORMAT A90 SELECT REF(a) ref, VALUE(a) FROM addr_list1 a; Теперь можно поменять описание таблицы, например, DEPT, чтобы она заимствовала адреса отделов из имеющегося списка, а не хранила вместе со своими данными: ALTER TABLE dept DROP (addr); ALTER TABLE dept ADD (addr REF address_typ SCOPE IS addr_list1); SELECT * FROM dept; UPDATE dept d SELECT * FROM dept; Фраза SCOPE IS при определении типа как ссылки на существующий объект необязательна, но позволяет фактически ссылаться только на объекты какой-нибудь объектной таблицы. Раскрытие ссылки делается с помощью специальной функции DEREF: COLUMN deref(addr) FORMAT A40 SELECT d.dname, DEREF(addr) FROM dept d; Однако при обращении к нижележащим атрибутам раскрытие может выполняться и неявно (неявное преобразование типов, присутствующее в Oracle-диалекте SQL): SELECT d.dname, d.addr.zip FROM dept d; вместо более правильного SELECT d.dname, DEREF(d.addr).zip FROM dept d; Методы объектовВыше было рассмотрено определение типа, содержащее описание атрибутов ("свойств"). Создадим тип сотрудников, в котором определен еще и метод: CREATE TYPE employee_typ AS OBJECT ( Для описания тела метода-функции необходимо создать тело типа (аналогия пакет - тело пакета в PL/SQL): CREATE TYPE BODY employee_typ IS Создадим таблицу объектов-сотрудников: DROP TABLE emp; CREATE TABLE emp OF employee_typ; INSERT INTO emp VALUES ( Пример обращения к методу: COLUMN home.location FORMAT A20 SELECT e.ename, e.home.location, e.days_at_company() FROM emp e; Виртуальные объектыПереводить в существующей БД табличные описания данных в объектные не всегда возможно, а иногда и не нужно. В силу разных обстоятельств может оказаться удобной имитация объектов на основе данных, хранимых в традиционных таблицах. Тогда к одним и тем же данным можно обращаться и через объектный интерфейс, и через табличный. Достигается это с помощью виртуальных объектов (object views), которых можно так назвать по аналогии с виртуальными таблицами (views). Для примера вернем описания и наполнение традиционным таблицам схемы SCOTT: EMP и DEPT. @?/sqlplus/admin/demobld sqlplus scott/tiger (Сценарий demobld.sql выводит нас из SQL*Plus). Упростим для примера описание типа EMPLOYEE_TYP: ALTER TYPE employee_typ DROP ATTRIBUTE (home); ALTER TYPE employee_typ ADD ATTRIBUTE (empno NUMBER); CONNECT scott/tiger ALTER TYPE employee_typ COMPILE; Построим таблицу виртуальных объектов типа EMPLOYEE_TYP по исходным данным, хранящимся в EMP: CREATE VIEW emp_ov OF employee_typ По своему поведению виртуальные объекты ничем не отличаются от первичных. Проверка ("объектного доступа" к табличным данным): SELECT e.ename, e.days_at_company () FROM emp_ov e; SELECT VALUE(e) FROM emp_ov e; SELECT REF(e) FROM emp_ov e; UPDATE emp_ov e SET e.ename = INITCAP(e.ename) SELECT ename FROM emp_ov; Возможность выполнения традиционных DML-операторов над базовыми таблицами, естественно, сохраняется: UPDATE emp SET ename = UPPER(ename) WHERE empno = 7934; SELECT ename FROM emp; Ссылки по теме
|
|