您的位置:首页 > 其它

两个关联表间如何建立触发器

2011-03-31 16:58 239 查看
实现功能描述:
表C由表A、表B关联生成(其中表A、表B在物理库中,表C在内存数据库中),表A、表B数据变化后通过触发器将变化后记录插入到小表C_inc中,通过小表触发,最后用内存库的实时同步功能将C_inc小表中的记录同步到内存库表C中。

问题描述:
如何将表A、表B变化后的数据插入到小表C_inc中

最初实现方案:
在物理库建立表A、表B关联的视图C_view,然后在视图C_view上建立触发器,通过视图上的触发器将表的变化数据触发到小表C_inc中。

遇到的问题
视图上怎么建立触发器?

通过查资料,在视图上建立的触发器为替代触发器,其与DML触发器不同,DML触发器是在DML操作之外运行的,而替代触发器则代替激发它的DML语句运行,代替触发器是行一级的。
替代触发器的用途:
1、允许对无法变更的视图进行修改,视图修改后触发基表数据修改
2、修改视图中嵌套表列的列
例:
create trigger ClassRoomInsert
instead of insert on class_room
declare
v_rooid rooms.room_id%TYPE;
begin
select room_id
into v_roomid
from rooms
where building = :new.building
and room_number = :new.room_number;

set room_id = v_roomid
where department = :new.department
and course = :new.course;
end;
经上所述,替代触发器实现的是允许无法变更的视图进行修改,而不是我想要的基表变化了,视图随之更新,根据视图的更新插入小表C_inc中记录。

第二种实现方案:
在触发器中进行2个表数据的关联,触发器如下:
CREATE OR REPLACE TRIGGER t_mmdb_on_balance_type
after insert or update on balance_type_attr
for each row
declare
begin
if inserting then
insert into mmdb_balance_type_inc(op_sn,op_type,op_time,BALANCE_TYPE_ID,BALANCE_TYPE_ATTR,ACCT_ITEMS,PRIORITY,CYCLE_UPPER_TYPE,CYCLE_UPPER,CYCLE_LOWER_TYPE,CYCLE_LOWER,PAYMENT_LIMIT_TYPE,PAYMENT_LIMIT)
select 0,'1',sysdate,a.BALANCE_TYPE,a.BALANCE_TYPE_ATTR,a.ACCT_ITEMS,b.PRIORITY,a.CYCLE_UPPER_TYPE,
a.CYCLE_UPPER,a.CYCLE_LOWER_TYPE,a.CYCLE_LOWER,a.PAYMENT_LIMIT_TYPE,a.PAYMENT_LIMIT
from BALANCE_TYPE_ATTR a,bss_acctbook_info b
where a.BALANCE_TYPE = b.acctbooktype
and a.BALANCE_TYPE = :new.BALANCE_TYPE;
elsif updating then
insert into mmdb_balance_type_inc(op_sn,op_type,op_time,BALANCE_TYPE_ID,BALANCE_TYPE_ATTR,ACCT_ITEMS,PRIORITY,CYCLE_UPPER_TYPE,CYCLE_UPPER,CYCLE_LOWER_TYPE,CYCLE_LOWER,PAYMENT_LIMIT_TYPE,PAYMENT_LIMIT)
select 0,'2',sysdate,a.BALANCE_TYPE,a.BALANCE_TYPE_ATTR,a.ACCT_ITEMS,b.PRIORITY,a.CYCLE_UPPER_TYPE,
a.CYCLE_UPPER,a.CYCLE_LOWER_TYPE,a.CYCLE_LOWER,a.PAYMENT_LIMIT_TYPE,a.PAYMENT_LIMIT
from BALANCE_TYPE_ATTR a,bss_acctbook_info b
where a.BALANCE_TYPE = b.acctbooktype
and a.BALANCE_TYPE = :new.BALANCE_TYPE;
end if;
end;

更新数据时报如下错误:
ORA-04091: table OCSBILLTEST.BALANCE_TYPE_ATTR is mutating, trigger/function may not see it
ORA-06512: at "OCSBILLTEST.T_MMDB_ON_BALANCE_TYPE", line 11
ORA-04088: error during execution of trigger 'OCSBILLTEST.T_MMDB_ON_BALANCE_TYPE'
基本意思是在是因为在TRIGGER中访问了变化表所引起的,ORACLE资料上说如INSERT语句仅影响一个行,触发器不把触发表当作变化表处理,也就是在trigger里面不要再访问trigger所在的表了。

修改后的实现方案:
在基表表A、表B上建立触发器,触发器上使用游标操作,进行2个表的关联操作,触发器如下:
CREATE OR REPLACE TRIGGER t_mmdb_on_balance_type
after insert or update on balance_type_attr
for each row
declare
cursor c_priority is
SELECT priority FROM BSS_ACCTBOOK_INFO where ACCTBOOKTYPE = :new.BALANCE_TYPE;
begin
if inserting then
for v_record in c_priority loop
insert into mmdb_balance_type_inc(op_sn,op_type,op_time,BALANCE_TYPE_ID,BALANCE_TYPE_ATTR,ACCT_ITEMS,PRIORITY,CYCLE_UPPER_TYPE,CYCLE_UPPER,CYCLE_LOWER_TYPE,CYCLE_LOWER,PAYMENT_LIMIT_TYPE,PAYMENT_LIMIT)
values(0,'1',sysdate,:new.BALANCE_TYPE,:new.BALANCE_TYPE_ATTR,:new.ACCT_ITEMS,v_record.priority,:new.CYCLE_UPPER_TYPE,
:new.CYCLE_UPPER,:new.CYCLE_LOWER_TYPE,:new.CYCLE_LOWER,:new.PAYMENT_LIMIT_TYPE,:new.PAYMENT_LIMIT);
end loop;
elsif updating then
for v_record in c_priority loop
insert into mmdb_balance_type_inc(op_sn,op_type,op_time,BALANCE_TYPE_ID,BALANCE_TYPE_ATTR,ACCT_ITEMS,PRIORITY,CYCLE_UPPER_TYPE,CYCLE_UPPER,CYCLE_LOWER_TYPE,CYCLE_LOWER,PAYMENT_LIMIT_TYPE,PAYMENT_LIMIT)
values(0,'2',sysdate,:new.BALANCE_TYPE,:new.BALANCE_TYPE_ATTR,:new.ACCT_ITEMS,v_record.priority,:new.CYCLE_UPPER_TYPE,
:new.CYCLE_UPPER,:new.CYCLE_LOWER_TYPE,:new.CYCLE_LOWER,:new.PAYMENT_LIMIT_TYPE,:new.PAYMENT_LIMIT);
end loop;
end if;
end;

由于自己在SQL方面知识比较欠缺,造成建一个关联表的触发器用了4个多小时,还好最后成功的解决了问题,将这之间遇到的问题及解决办法整理了一下,希望能对有同样困扰的人有所帮助。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: