Oracle 触发器将所有插入/更新写入文件

Posted

技术标签:

【中文标题】Oracle 触发器将所有插入/更新写入文件【英文标题】:Oracle Trigger to write all Insert/Updates to File 【发布时间】:2012-02-06 19:41:10 【问题描述】:

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

有办法实现吗?

【问题讨论】:

您可能希望对日志表使用插入前更新触发器,然后以批处理方式提取出来进行处理(每天晚上,无论如何)。请务必添加一个“action_date”日期字段(或时间戳),您以后可以使用它来根据 ins/upd 发生的时间有选择地提取数据。 感谢 tbone,这将是一个很好的解决方案。但是在不更改应用程序的情况下,我认为我需要在表上放置一个更新触发器,并在该列的后期添加一个额外的“最后更新/更改列”。或者有 oracle 的内置功能吗? 【参考方案1】:

您需要创建在更改表行后执行的触发器,并使用 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/

希望对你有帮助...

【讨论】:

正如@tbone 评论的那样,您可能需要考虑使用 BEFORE 触发器,因为它们比 AFTER 触发器更有效 - 来自 oracle 文档:BEFORE 行触发器比 AFTER 行触发器更有效。使用 AFTER 行触发器,必须为触发器读取一次受影响的数据块(逻辑读取,而不是物理读取),然后再为触发语句读取一次。或者,对于 BEFORE 行触发器,数据块必须对触发语句和触发器都只读取一次。【参考方案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”法令)来避免这种情况,这通常会导致我所看到的数据不一致(或更糟)。

【讨论】:

【参考方案3】:

是的,here 您有一个 update 部分的示例。

您只需要对insert 部分执行类似的操作即可。

【讨论】:

以上是关于Oracle 触发器将所有插入/更新写入文件的主要内容,如果未能解决你的问题,请参考以下文章

如何将一个触发器写入 SQL Server 2008 的所有表

oracle之检查点(Checkpoint)

oracle之检查点(Checkpoint)

当其它程序写入记录数据库中后,我要立即取得其输入的数据,以写入到我的数据库中,用C#怎么做?

Greenplum loader 不会将数据写入管道文件

怎么把二进制流插入oracle的clob字段