oracle instead of update,38.2.2 使用INSTEAD OF 触发器

38.2.2 使用INSTEAD OF 触发器

如果创建一个对象视图,则可以使用INSTEAD OF 触发器来告诉Oracle 如何更新作为视图一部分的基表。可以在对象视图或标准关系视图中使用INSTEAD OF 触发器。

例如,如果一个视图涉及两个表的连接,那么用户在视图中更新记录的能力有限。但是,如果使用INSTEAD OF 触发器,那么当用户试图通过该视图更改值时,可以告诉Oracle 如何在表中更新、删除或插入记录。INSTEAD OF 触发器中的程序代码代替了输入的update、delete 或insert 命令。

例如,有一个连接BOODSHELF 表与BOOKSHELF_AUTHOR 表的视图: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

whereAuthorName='W. P. KINSELLA';

AUTHORNAME PUBLISHER

--------------------------------------------- ----------

W. P. KINSELLA MARINER

W. P. KINSELLA BALLANTINE

如果试图更新Publisher 的值,则更新会失败:update AUTHOR_PUBLISHER

setPublisher='MARINER'

whereAuthorName='W. P. KINSELLA';

setPublisher='MARINER'

*

ERROR at line 2:

ORA-01779: cannot modify a column which maps to a

non key-preserved table

问题是Oracle 不能确定BOOKSHELF 表中哪些记录中的哪些出版商要更新。为了通过该视图执行更新,需要使用INSTEAD OF 触发器。

在下面的程序清单中,创建了AUTHOR_PUBLISHER 视图的一个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

setPublisher= :new.Publisher

whereTitle= :old.Title;

end if;

if :old.AuthorName<>:new.AuthorName

then

update BOOKSHELF_AUTHOR

setAuthorName= :new.AuthorName

whereTitle= :old.Title;

end if;

end;

/

该触发器的***部分命名触发器,并通过instead of 子句描述其用途。顾名思义该触发器的功能很明显:用于支持对AUTHOR_PUBLISHER 视图执行的update 命令。它是一个行级触发器;可以处理每个变化的行,如下所示:create trigger AUTHOR_PUBLISHER_UPDATE

instead of UPDATE on AUTHOR_PUBLISHER

for each row

该触发器的下一部分告诉Oracle 如何处理update 操作。首先要检查的是触发器体内部的Publisher 值。如果旧的Publisher 值等于新的Publisher 值,则不做任何修改。如果两个值不相同,则BOOKSHELF 表被更新为新的Publisher 值:begin

if :old.Publisher<>:new.Publisher

then

update BOOKSHELF

setPublisher= :new.Publisher

whereTitle= :old.Title;

end if;

触发器的下一部分判断AuthorName 的值是否有变化。如果AuthorName 的值被修改,则更新BOOKSHELF 表,以反映新的AuthorName 值:if :old.AuthorName<>:new.AuthorName

then

update BOOKSHELF_AUTHOR

setAuthorName= :new.AuthorName

whereTitle= :old.Title;

end if;

因此,该视图依赖两个表—— BOOKSHELF 和BOOKSHELF_AUTHOR—— 并且该视图的update 操作可以更新一个表也可以同时更新两个表。为了支持对象视图而引入的INSTEADOF 触发器是应用程序开发的有力工具。

现在可以直接更新AUTHOR_PUBLISHER 视图并使触发器恰当地更新基表。例如,以下命令将更新BOOKSHELF 表:update AUTHOR_PUBLISHER

setPublisher='MARINER'

whereAuthorName='W. P. KINSELLA';

2 rows updated.

可以通过查询BOOKSHELF 表,来验证update 操作:select Publisher from BOOKSHELF

where Title in

(select Title from BOOKSHELF_AUTHOR

whereAuthorName='W. P. KINSELLA');

PUBLISHER

--------------------

MARINER

MARINER

INSTEAD OF 触发器的功能十分强大。如本示例所示,使用PL/SQL 内可用的流控制逻辑,可以使用该触发器在不同的数据库表上进行操作。在处理对象视图时,可以使用INSTEADOF 触发器将对象视图的DML 重定位到这些视图的基表上。

【责任编辑:云霞 TEL:(010)68476606】

点赞 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值