實現功能描述:
表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個多小時,還好最後成功的解決了問題,將這之間遇到的問題及解決辦法整理了一下,希望能對有同樣困擾的人有所協助。