Программирование >>  Oracle 

1 ... 332 333 334 [ 335 ] 336 337 338 ... 469


Использование объектно-реляционных средств 1423

ности объектной таблицы доступны: из нее можно выбрать ссылки на объекты, вложенная таблица создана и т.д. Преимущество такой реализации в том, что мы явно указываем, как соединять таблицы ЕМР и DEPT, используя естественное отношение - главный/подчиненный .

Итак, создано объектно-реляционное представление, позволяющее запрашивать данные. Но изменять его данные пока нельзя:

scott@TKYTE816> update TABLE (select p.emps

2 from dept or p

3 where deptno = 2 0)

4 set ename = lower(ename)

set e*name = lower(ename) RCR at line 4:

ORA-25015: cannot perform on this nested table view column

scott@TKYTE816> declare

2 l emps emp tab type;

3 begin

4 select p.emps into l emps

5 from dept or p

6 where deptno = 10;

8 for i in 1 .. l emps.count

9 loop

10 l emps(i).ename := lower(l emps(i).ename);

11 end loop; 12

13 update dept or

14 set emps = l emps

15 where deptno = 10;

16 end;

17 / declare

ERROR at line 1:

ORA-01733: virtual column not allowed here ORA-06512: at line 13

Необходимо заставить представление обновляться . У нас реализовано сложное сопоставление реляционных данных объектно-реляционным (на самом деле оно может иметь любую степень сложности). Так как же заставить представление обновляться ? Сервер Oracle обеспечивает для этого соответствующий механизм - триггеры INSTEAD 0F. Можно реализовать алгоритм, который должен выполняться сервером Oracle вместо (INSTEAD OF) стандартного при изменении содержимого представления. Чтобы продемонстрировать это, давайте обеспечим возможность изменения показанного ранее представления.

Сервер Oracle позволяет создать триггер INSTEAD OF по представлению DEPT OR и по любому типу вложенной таблицы, входящей в это представление. Создав триггер



1424

Глава 20

по столбцам вложенной таблицы, можно изменять столбец вложенной таблицы так, бу это обычная таблица. Соответствующий триггер может иметь следующий вид:

scott@TKYTE816> create or replace trigger EMPS IO UPDATE

2 instead of UPDATE on nested table emps of dept or

3 begin

4 if (:new.empno = :old.empno)

5 then

6 update emp

7 set ename = :new.ename, job = :new.job, mgr = :ne.mgr,

8 hiredate = :new.hiredate, sal = :new.sal, -> comm = :new.comm

9 where empno = :old.empno;

10 else

11 raise application error(-20001,Значение столбца empno -> изменять нельзя);

12 end if;

13 end;

14 /

Trigger created.

Как видите, триггер будет срабатывать при изменении (INSTEAD OF UPDATE) столбца типа вложенной таблицы, EMPS, представления DEPT OR. Он будет срабат1вать для каждой изменяемой строки вложенной таблицы и имеет доступ к значениям до и после изменения (:OLD и :NEW), как и обычный триггер. В данном случае понятно, что надо делать, - изменить строку таблицы ЕМР с соответствующим значением EMPNO, задав ее столбцам новые значения. В этом триггере я принудительно запрещаю изменять первичный ключ (мы используем объектно-реляционные средства, но это не значит, что можно нарушать основные принципы проектирования реляционных баз данных).

Теперь, выполним следующие операторы:

scott@TKYTE816> update TABLE (select p.emps

2 from dept or p

3 where deptno = 20)

4 set ename = lower(ename)

5 rows updated.

scott@TKYTE816> select ename from emp where deptno = 20; ENAME

smith jones scott adams ford

scott@TKYTE816> select ename

2 from TABLE(select p.emps

3 from dept or p

4 where deptno = 20);



Использование объено-реляционн1х средств 142 5

ENAME

smith jones scott adams ford

Как видите, изменение вложенной таблицы успешно преобразовано в изменение реляционной таблицы, как и ожидалось. Так же легко написать триггеры на события INSERT и DELETE, поскольку UPDATE - самый сложный случай. Так что на этом и остановимся.

Если сейчас выполнить следующее изменение:

scott@TKYTE816> declare

2 l emps emp tab type;

3 begin

4 select p.emps into l emps

5 from dept or p

6 where deptno = 10; 7

8 for i in 1 .. l emps.count

9 loop

10 l emps(i).ename := lower(l emps(i).ename);

11 end loop;

13 update dept or

14 set emps = l emps

15 where deptno = 10;

16 end;

17 /

declare *

ERROR at line 1:

ORA-01732: data manipulation operation not legal on this view

ORA-06512: at line 13

то окажется, что при выполнении выдается сообщение об ошибке. Странно. Не должен ли сработать созданный ранее триггер? На самом деле - нет. Только изменения вложенной таблицы, связанные с извлечением ее данных, вызовут срабатывание триггера. Триггер срабатывает, только если с вложенной таблицей работают как с обычной таблицей. Мы же не выполняем операцию над большим количеством данных вложенной таблицы, а только изменяем столбец представления DEPT OR. Чтобы поддержать работу подобного кода (и изменений других скалярных столбцов представления DEPT OR), необходимо создать триггер INSTEAD OF для представления DEPT OR. Этот триггер будет обрабатывать значения :OLD.EMPS и :NEW.EMPS как множества следующим образом.

1. Удалять из таблицы ЕМР все записи, значение EMPNO которых б1ло в наборе :OLD, но отсутствует в наборе :NEW. Для этого прекрасно подходит реляционный оператор MINUS.



1 ... 332 333 334 [ 335 ] 336 337 338 ... 469

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика