Об’єкти в 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 (
zip CHAR(6),
location VARCHAR2(200))
/


Скористаємося цим типом для опису співробітників і відділів:


CREATE TABLE dept (
dname VARCHAR2(50),
deptno NUMBER CONSTRAINT pk_dept PRIMARY KEY,
addr address_typ);


CREATE TABLE emp (
ename VARCHAR2(50),
empno NUMBER CONSTRAINT pk_emp PRIMARY KEY,
deptno NUMBER CONSTRAINT fk_emp REFERENCES dept,
home address_typ);


Перевіримо опису створених об’єктів:


DESCRIBE address_typ
DESCRIBE dept
DESCRIBE emp


Приклад закладу співробітників і відділів:


INSERT INTO dept VALUES (
“Sales”,
10,
address_typ(“123456”, “Boston 123… “));


INSERT INTO emp VALUES (
“Smith”,
1001,
10,
address_typ(“123333”, “Boston 567… “));


Тут вираз ADDRESS_TYP (“123333”, “Boston 567 …”) означає звернення до конструктора об’єкту, тобто до функції, автоматично створюваної СУБД при закладі нового типу для можливості створювати нові об’єкти цього типу з потрібними значеннями атрибутів. Поняття конструктора загальноприйнято в об’єктному підході. У наведених реченнях INSERT простановку адреси можна оформити трохи інакше, додавши, відповідно з духом об’єктного підходу, ключове слово NEW перед зверненням до конструктору:


INSERT INTO emp VALUES (
“Allen”,
1002,
10,
NEW address_typ(“123456”, “Boston 123… “));


Перевірка:


COLUMN dname FORMAT A20
COLUMN ename FORMAT A20
COLUMN addr FORMAT A40
COLUMN home FORMAT A40


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
SET home = address_typ(“123457”, “Boston 777… “)
WHERE ename = “Allen”;


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
(NEW address_typ(“123456”, “Boston 123… “));


або


INSERT INTO addr_list1 VALUES
(address_typ(“123458”, “Boston 123… “));


INSERT INTO addr_list2 VALUES
(address_typ(“123333”, “Boston 567… “));


Перегляд:


COLUMN location FORMAT A30


SELECT * FROM addr_list1;


SELECT VALUE(a) FROM addr_list1 a;


SELECT e.ename, e.home
FROM addr_list1 a, emp e
WHERE VALUE(a) = e.home;


(Функція VALUE спеціально придумана для повернення значень об’єктів, а не атрибутів об’єктів окремо).


Посилання на об’єкт


Об’єкти, заведені в об’єктних таблицях, мають одну перевагу перед об’єктами, зазначеними як атрибут рядки: на них можна посилатися. Посилання є унікальний внутрішній ідентифікатор об’єкта, і отримати його можна за допомогою функції REF:


COLUMN ref FORMAT A90
COLUMN value FORMAT A40


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
SET d.addr =
(SELECT REF(a)
FROM addr_list1 a
WHERE VALUE(a)= address_typ(“123458”, “Boston 123… “))
WHERE d.deptno = 10;


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 (
ename VARCHAR2(50),
hiredate DATE,
deptno NUMBER,
home REF address_typ,
MEMBER FUNCTION days_at_company RETURN NUMBER)
/


Для опису тіла методу-функції необхідно створити тіло типу (аналогія пакет – тіло пакета в PL / SQL):


CREATE TYPE BODY employee_typ IS
MEMBER FUNCTION days_at_company RETURN NUMBER IS
BEGIN
RETURN TRUNC(SYSDATE-hiredate);
END;
END;
/


Створимо таблицю об’єктів-співробітників:


DROP TABLE emp;


CREATE TABLE emp OF employee_typ;


INSERT INTO emp VALUES (
“Scott”,
SYSDATE,
10,
(SELECT REF(a) FROM addr_list1 a
WHERE VALUE(a) = address_typ(“123458”, “Boston 123… “)));


Приклад звернення до методу:


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
WITH OBJECT IDENTIFIER (empno) AS
SELECT e.ename, e.hiredate, e.deptno, e.empno FROM emp e;


По своїй поведінці віртуальні об’єкти нічим не відрізняються від первинних. Перевірка (“об’єктного доступу” до табличним даними):


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)
WHERE e.empno = 7934;


SELECT ename FROM emp_ov;


Можливість виконання традиційних DML-операторів над базовими таблицями, природно, зберігається:


UPDATE emp SET ename = UPPER(ename) WHERE empno = 7934;


SELECT ename FROM emp;

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*