2012-01-10 130 views
5

我想在表格上放置一个触发器,该表格将所有插入/更新的数据写入一个附加的日志文件,以便使用外部工具进行处理。Oracle触发器将所有插入/更新写入文件

是否可以实现这一目标?

+1

您可能希望在插入更新触发器前使用一个日志表,然后以批处理方式(每晚,不管)进行处理。一定要添加一个“action_date”日期字段(或时间戳),您可以稍后使用该字段根据发生的ins/upd的时间来选择性地提取数据。 – tbone 2012-01-10 13:08:03

+0

感谢tbone,这将是一个很好的解决方案。但是在不改变应用程序的情况下,我想我需要在表格上添加一个更新触发器,在该列的后面添加一个额外的“最新更新/更改列”。或者说甲骨文在这个功能的构建? – user85155 2012-01-11 09:30:19

回答

5

您需要创建在表行更改后执行并使用UTL_FILE包写入日志文件的触发器。

的UTL_FILE包的信息可以在这里找到: http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/u_file.htm

和触发文档可以在这里找到: http://docs.oracle.com/cd/B10501_01/appdev.920/a96590/adg13trg.htm

有一个类似的答案,你在找什么在这里: http://bytes.com/topic/oracle/answers/762007-trigger-output-text-file

有关使用PL/SQL在此处写入文件的详细信息,请访问: http://www.devshed.com/c/a/Oracle/Writing-to-Text-Files-in-Oracle-PLSQL/

希望它有帮助...

+1

正如@tbone所评论的那样,您可能需要考虑使用BEFORE触发器,因为它们比AFTER触发器更高效 - 从Oracle Docs:BEFORE行触发器比AFTER行触发器稍微高效。使用AFTER行触发器时,必须为触发器读取受影响的数据块(逻辑读取,而非物理读取),然后再次触发语句。或者,使用BEFORE行触发器时,触发语句和触发器的数据块只能读取一次。 – Ollie 2012-01-10 13:33:25

1

是的,here你有一个update部分的例子。

你只需要做一个类似的insert部分。

2

我会避免在DML时间写入文件系统,但会在每晚(或任何频率)的批处理过程中提取数据。

从您的OP中,不清楚您是否需要更新后的“新”数据或更新前的“旧”数据。如果你只是想要最新的数据,为什么不只是添加modified_date字段(日期或时间戳类型)并通过触发器来更新。

create table test 
(
id number, 
val varchar2(100), 
modified_date date default sysdate not null 
) 
; 

CREATE OR REPLACE TRIGGER TR_TEST_BU 
BEFORE UPDATE 
ON TEST REFERENCING NEW AS NEW OLD AS OLD 
FOR EACH ROW 
begin 
    :new.modified_date := sysdate; 
end; 

insert into test(id, val) values (1, 'Insert 1'); 
commit; 

select * from test; 

exec dbms_lock.sleep(5); 
update test set val = 'Update 1' where id = 1; 
commit; 

select * from test; 

如果在更新前需要的旧数据(或你所关心的已删除的数据),那么你就修改触发旧的或删除的值写入历史表,然后从那里提取数据。

另请注意,向表中添加触发器会减慢关联的DML活动。一些商店希望通过用业务逻辑规则替换触发器(“所有应用程序必须更新modifed_date”edict)来避免这种情况,这通常会导致我看到的数据不一致(或更糟糕)。