日期:2014-05-16 浏览次数:20520 次
create or replace view AUTHOR_PUBLISHER as select BA.AuthorName, Title, B.Publisher from BOOKSHELF_AUTHOR BA inner join BOOKSHELF B using (Title);可以从该视图中选择相应的值—— 而且如果使用INSTEAD OF 触发器,就可以通过该视图执行数据操作。考虑以下记录:
select AuthorName, Publisher from AUTHOR_PUBLISHER where AuthorName = 'W. P. KINSELLA'; AUTHORNAME PUBLISHER --------------------------------------------- ---------- W. P. KINSELLA MARINER W. P. KINSELLABALLANTINE 如果试图更新Publisher 的值,则更新会失败:
update AUTHOR_PUBLISHER set Publisher = 'MARINER' where AuthorName = 'W. P. KINSELLA'; set Publisher = 'MARINER' * ERROR at line 2: ORA-01779: cannot modify a column which maps to a non key-preserved table问题是Oracle 不能确定BOOKSHELF 表中哪些记录中的哪些出版商要更新。为了通过该视图执行更新,需要使用INSTEAD OF 触发器。
create or replace trigger AUTHOR_PUBLISHER_UPDATE instead of UPDATE on AUTHOR_PUBLISHER for each row begin if :old.Publisher <> :new.Publisher then update BOOKSHELF set Publisher = :new.Publisher where Title = :old.Title; end if; if :old.AuthorName <> :new.AuthorName then update BOOKSHELF_AUTHOR set AuthorName = :new.AuthorName where Title = :old.Title; end if; end;该触发器的第一部分命名触发器,并通过instead of 子句描述其用途。顾名思义该触发器的功能很明显:用于支持对AUTHOR_PUBLISHER 视图执行的update 命令。它是一个行级触发器;可以处理每个变化的行,如下所示:
begin if :old.Publisher <> :new.Publisher then update BOOKSHELF set Publisher = :new.Publisher where Title = :old.Title; end if;触发器的下一部分判断AuthorName 的值是否有变化。如果AuthorName 的值被修改,则更新BOOKSHELF 表,以反映新的AuthorName 值:
if :old.AuthorName <> :new.AuthorName then update BOOKSHELF_AUTHOR set AuthorName = :new.AuthorName where Title = :old.Title; end if;因此,该视图依赖两个表—— BOOKSHELF 和BOOKSHELF_AUTHOR—— 并且该视图的update 操作可以更新一个表也可以同时更新两个表。为了支持对象视图而引入的INSTEADOF 触发器是应用程序开发的有力工具。
update AUTHOR_PUBLISHER set Publisher = 'MARINER' where AuthorName = 'W. P. KINSELLA'; 2 rows updated.
select Publisher from BOOKSHELF where Title in (select Title from BOOKSHELF_AUTHOR where AuthorName = 'W. P. KINSELLA'); PUBLISHER -------------------- MARINER MARINER