【发布时间】:2015-01-27 02:53:38
【问题描述】:
我有两个表:delivery_records 和delivery_summary。我已经简化了表格来演示
select *
from delivery_records
FILTERLIST PRICE_DATE PRICE_VALUE
-------------------------------------
FL_1 1/1/2015 1
FL_1 1/1/2015 2
FL_1 1/1/2015 3
FL_2 1/1/2015 8
FL_2 1/1/2015 9
在对delivery_records 上的每一行进行插入或更新后,我有一个触发器,它会触发过程summarize_records,以便在每次修改delivery_records 表后立即更新delivery_summary 表。
CREATE OR REPLACE TRIGGER SNAPSHOT_TRIG
AFTER INSERT OR UPDATE ON DELIVERY_RECORDS FOR EACH ROW
Declare
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
dbms_output.put_line('Starting trigger');
SUMMARIZE_RECORDS(:new.filterlist, trunc(sysdate));
COMMIT;
dbms_output.put_line('Trigger ended');
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('SQL Error: ' || SQLCODE || ' - ' || SUBSTR(SQLERRM, 1, 100));
END DELIV_SNAPSHOT_UPDATE;
过滤列表是一组相关的交付记录。 summarise_records 存储过程通过在 delivery_records 表上运行 select 然后将结果插入到 delivery_summary 表中来汇总每个日期的每个过滤器列表的交付计数,我希望这会产生以下结果:
select * from delivery_summary
FILTERLIST DATE DELIVERY_COUNT
------------------------------------
FL_1 1/1/2015 3
FL_2 1/1/2015 2
这按预期工作,但似乎触发器缺少为每个过滤器列表插入的最后一条记录。几乎就像触发器没有触发一样。我做了一些研究,有人暗示自治事务看不到当前事务的记录。这是我看到的表格,除非我运行某种无操作更新以导致触发器再次触发。
select * from delivery_summary
FILTERLIST DATE DELIVERY_COUNT
------------------------------------
FL_1 1/1/2015 2
FL_2 1/1/2015 1
据我了解,作为“后”触发器,该行对于我的摘要过程应该是可见的。我必须将程序设置为 pragma 自治,因为我在正在触发的表上进行选择。我知道这是禁忌,但这似乎是满足实时汇总表要求的唯一方法。
有没有更好的方法来做到这一点?这似乎是触发器的完美用例。
【问题讨论】:
-
使用视图可能比尝试使用触发器维护摘要状态更容易。
-
我支持使用视图或可能是物化视图的建议。取决于delivery_records 表的更新频率与delivery_summary 表的查看频率。
-
不幸的是,我遗漏了很多外围功能,因此这不会是一个荒谬的长问题。在交付记录的数量和在视图上报告和汇总的列数之间并不能提供所需的性能。并且某些列被冻结(未更新)历史日期以提供审计日志。视图无法提供此功能。
-
@AndyIngraham - 物化视图可能,但是是的,这取决于
summarize_records在做什么。当然,触发器有其自身的性能损失,尤其是当您最终有多个插入尝试更新同一个摘要时。无论如何,不,即使在后触发器中,您插入的数据对自治事务也不可见 - 这就是使其自治的原因,因为它在当前(未提交的)事务之外。