Моделювання груп об’єктів в Oracle, Інтеграція додатків і даних, Бази даних, статті

Зміст



Об’єктний підхід до моделювання БД, безумовно, має свою привабливість, хоча, як зауважувалося у попередній статті цінність його перебільшувати не варто, так як і він не позбавлений власних проблем і обмежень (до слова сказати, відомих задовго до середини 90-х років, коли провідні постачальники СУБД взяли його на озброєння). Однак підхід є, і якось вирішувати задачу моделювання він зобов’язаний. У попередній статті йшлося про те, як в Oracle можна створювати і зберігати окремі об’єкти. У житті цього недостатньо, і потрібно мати можливість моделювати групи об’єктів: набори адрес, списки співробітників і т. д.


Така можливість передбачалася, наприклад, в мережевій моделі даних, історично передувала реляційної, і проектувалася у вигляді розширення реляційної творцем останньої Е. Коддом (в силу ряду причин це розширення було проігноровано розробниками промислових “реляційних” СУБД). Тут будуть розглянуті можливості моделювання груп об’єктів, реалізовані в Oracle останніх версій (8, 9).


Таблиці збережених і синтезованих об’єктів


Перша можливість моделювання груп з об’єктів в Oracle відома по попередній статті: це таблиці “споконвічних” об’єктів (object tables) і таблиці “віртуальних”, або “синтезованих” об’єктів (object views). Споконвічні об’єкти зберігаються як самостійні сутності в БД, а синтезовані дають тільки видимість об’єктів (за споживчими властивостями майже не відрізняються від справжніх об’єктів) на основі даних, збережених у звичайних або об’єктних таблицях.


І ті й інші дозволяють мати в БД невпорядковані списки об’єктів. Нижче наводиться приклад створення двох списків співробітників, які проживають в Москві та Ленінграді. Належність співробітників відділам задається спеціальною таблицею:


DROP TYPE employee_typ FORCE;
DROP TABLE e_moscow;
DROP TABLE e_leningrad;
DROP TABLE employment;


CREATE TYPE employee_typ AS OBJECT (
ename VARCHAR2(50),
job VARCHAR2(10))
/


CREATE TABLE e_moscow OF employee_typ;


CREATE TABLE e_leningrad OF employee_typ;


INSERT INTO e_moscow VALUES (
“Scott”,
“Manager”);


INSERT INTO e_leningrad VALUES (
“Smith”,
“Salesman”);


CREATE TABLE employment (
dname VARCHAR2(50),
employee REF employee_typ);


INSERT INTO employment VALUES (
“Operations”,
(SELECT REF(m) FROM e_moscow m WHERE m.ename = “Scott”));


Цей спосіб, проте, не позбавлений своїх обмежень. Наприклад, за даними таблиці EMPLOYMENT не можна зрозуміти, чи проживає співробітник в Москві чи Ленінграді. Не можна переселити співробітника з Москви в Ленінград (Можна тільки видалити його з однієї таблиці і створити в інший об’єкт з тими ж атрибутами) і так далі.


Колекції


Іншу можливість по угрупованню об’єктів дають “колекції”. Вони дозволяють зберігати в поле “звичайної” таблиці список. Елементами списку можуть бути скаляри (числа, рядки), об’єкти або посилання на самостійно існуючі об’єкти.


У Oracle вони можуть бути двох видів: вкладені таблиці і масиви типу VARRAY.


Вкладені таблиці


Термін, обраний для цього виду колекцій здається не зовсім вдалим. Мова насправді йде про моделюванні не таблиць, а списків. На відміну від попереднього прикладу побудуємо таблицю DEPARTMENTS з переліком відділів, причому в рядку про кожному відділі будемо зберігати список співробітників. Попередньо, однак, потрібно буде створити тип для такого поля-списку:


CREATE TYPE employee_nlist_typ AS TABLE OF employee_typ
/


CREATE TABLE department (
dname VARCHAR2(20),
emps employee_nlist_typ)
NESTED TABLE emps STORE AS emps_nt_tab;


Фраза NESTED TABLE – чисто технічна. Вона зобов’язана тому, що фізично Oracle буде зберігати в поле EMPS не список об’єктів-співробітників, а список їх системних ідентифікаторів, присвоєних при приміщенні самих співробітників у спеціально створювану для таблиці DEPARTMENT службову таблицю. Таким чином при використанні вкладених таблиць значення елементів збережених списків фізично завжди зберігаються у спеціальній окремій таблиці, яку ми зобов’язані придумати назву. У такому рішенні є своя логіка, тому що для цієї спеціальної таблиці ми можемо вказати власні характеристики зберігання і деякі інші речі.


Ось як можна заповнити таблицю відділів:


INSERT INTO department VALUES (
“Operations”,
employee_nlist_typ (
employee_typ (“Scott”, “Manager”),
employee_typ (“Smith”, “Salesman”)
)
);


У відділі Operations тепер два співробітники:


COLUMN emps FORMAT A60 WORD


SELECT * FROM department;


За термінологією попередньої статті співробітники в таблиці DEPARTMENT – “об’єктні атрибути”. Інший спосіб змоделювати ситуацію “співробітники-відділи” за допомогою колекції – скористатися списком посилань на співробітників, реально існуючих у власних таблицях.


Робота в PL / SQL


Ось як можна працювати з вкладеними таблицями в PL / SQL:


DECLARE
ee employee_nlist_typ;
BEGIN
SELECT emps INTO ee FROM department WHERE dname = “Operations”;
DBMS_OUTPUT.PUT_LINE(ee(1).ename);
DBMS_OUTPUT.PUT_LINE(ee(2).ename);
END;
/


У цьому прикладі для спрощення використані передумови про те, що (а) відділ з назвою “Operations” лише один і (в) співробітників в ньому – [принаймні] двоє.


Масиви типу VARRAY


Масиви типу VARRAY споживацьки багато в чому схожі на вкладені таблиці, але мають і ряд істотних технічних і зовнішніх відмінностей. Наприклад, вони зобов’язані мати обмеження на максимальне число елементів в конкретних масивах, на зразок типу VARCHAR2. Ще вони не вимагають для зберігання даних службової таблиці, на зразок вкладеної таблиці. Є й інші відмінності. Фірма Oracle радить використовувати вкладені таблиці, якщо потрібно зберігати невпорядковані списки і VARRAY, якщо потрібно зберігати впорядковані.


Приклад використання для угруповання співробітників колекції VARRAY може виглядати так:


CREATE TYPE employee_vlist_typ AS VARRAY(20) OF employee_typ
/


CREATE TABLE department1 (
dname VARCHAR2(15),
emps employee_vlist_typ
);


Цим типом ми заборонили відділам мати більше 20-и співробітників.


Додавання нового відділу робиться як і для вкладених таблиць:


INSERT INTO department1 VALUES (
“Operations”,
employee_vlist_typ (
employee_typ (“Scott”, “Manager”),
employee_typ (“Smith”, “Salesman”)
)
);


Наведений вище код на PL / SQL для масиву співробітників VARRAY пропрацює так само.


Перетворення колекцій


Як і слід було б очікувати від СУБД Oracle, щільна, а не поверхнева робота з колекціями як засіб моделювання груп об’єктів вимагає знання великої кількості “деталей”. Тут не місце роз’яснювати їх усі, але одну важливу для колекцій можливість варто навести. Мається на увазі розгортання колекції в список рядків, такий звичний для традиційної роботи.


Для того, щоб подивитися список співробітників відділу “Operations” у більш звичному вигляді, слід скористатися спеціальною функцією TABLE:


SELECT * FROM TABLE(SELECT emps FROM department);


До аргументу функції TABLE (це вкладений SELECT) є одна нагальна прохання: повертати одну і тільки колекцію. Наші дані це забезпечують, а інакше вкладений SELECT потрібно було б підправити.


Аналогічний приклад для масиву VARRAY:


SELECT ename FROM TABLE(SELECT emps FROM department1);


Чудово, що це перетворення вирішує завдання і зміни списку засобами SQL:


INSERT INTO TABLE(SELECT emps FROM department)
VALUES (“Allen”, “Salesman”);


SELECT * FROM TABLE(SELECT emps FROM department);


(Цей варіант не спрацює, однак, для масиву VARRAY, який в БД поводиться, по суті, як скаляр, допускаючи зміну поля-списку як єдиного, вже сформованого цілого). Якщо б можливість такого перетворення відсутня, додати співробітника до відділу або видалити можна було б тільки програмним способом, найпростіше в PL / SQL.


Природно, ніхто не заважає здійснити і масову вставку:


INSERT INTO TABLE(SELECT emps FROM department)
SELECT ename, job FROM emp;


Для зворотного перетворення, з таблиці в колекцію, потрібно більш складна конструкція:


SELECT
CAST (MULTISET(SELECT ename, job FROM emp) AS employee_nlist_typ)
FROM DUAL;


Однак таке перетворення на практиці менш затребуване.

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


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

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

Ваш отзыв

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

*

*