DB2 for i触发器 - 每个语句一次,但比较值之前和之后

问题描述 投票:0回答:3

在DB2 for IBM i中,是否可以创建一个每个语句运行一次的触发器,但是能够遍历所有受影响的行以确定是否有任何值实际更改?

用例是使用基础表上的触发器更新物化查询表(MQT)。但是,如果值实际发生了变化,我们只想刷新MQT。如果我们创建每行运行一次的触发器,我们就能够获得所需的功能。但是,如果我们一次插入,更新和/或删除多行,则会为每一行运行“刷新”语句。目前,我们系统上的MQT需要大约10秒钟。

只是希望有一种方法可以使用触发器集来为每个语句运行一次,但仍然可以访问每个单独行的before和after值。我无法找到任何表明它是否可能的东西。虽然我怀疑它不是。

如果有其他方法可以有效地自动刷新MQT,我也对此持开放态度。

db2 database-trigger db2-400 materialized-views
3个回答
0
投票

例:

create table test (id int not null primary key, a int)@
create table test_mqt (cnt) as (select sum(a) from test) data initially deferred refresh deferred maintained by user@

insert into test values (1, 1), (2, 1), (3, 1) with nc@

create or replace trigger test_aus 
after update on test
referencing 
new table as n
old table as o
for each statement
mode db2sql
begin atomic
  if (exists (select 1 from n,o where n.id=o.id and n.a<>o.a)) then
    refresh table test_mqt;
  end if;
end@

-- trigger IS NOT fired after the following update
update test set a=1 with nc@
-- the following select returns 0
select cnt from test_mqt@

-- trigger IS fired after the following update
update test set a=2 with nc@
-- the following select returns 6
select cnt from test_mqt@

1
投票

是的,文档是here。但是,根据您尝试执行此操作的方式,IBM i命令ADDPFTRG和SQL CREATE TRIGGER之间存在一些差异。

ADDPFTRG似乎不支持语句级触发器,但CREATE TRIGGER确实支持。

使用语句级别触发器时,可以使用引用受影响的行

REFERENCING OLD TABLE AS ___
            NEW TABLE AS ___

您可以使用SQL语句处理旧表引用和新表引用,就像它们是常规表一样。

为了清楚起见,OLD TABLE引用受影响的行,就像SQL语句运行之前一样,而NEW TABLE引用受影响的行,因为它们将在SQL语句完成之后。


0
投票

我觉得让触发器运行刷新是没有意义的......

触发器+ MQT的重点是让触发器直接更新MQT表。这样你只需要处理已经改变的确切行;而不是强制DB再次读取整个基表。

create or replace trigger test_aus 
after update on test
referencing 
new row as n
old row as o
for each row
mode db2sql
begin atomic
  if n.a <> o.a then
    update test_mqt set cnt = cnt + n.a - o.a;
  end if;
end@

但请注意,如果a的变化是您感兴趣的全部,那么您可以将触发器定义为

after update of a on test 
for each row 

这样,触发器只有在实际更新时才会触发。

如果你在一次更新时设置了比RPG(或SQL)单行更新更多的SQL集,那么语句触发器可能是值得的......

像这样的东西:

create or replace trigger test_aus 
after update on test
referencing 
new table as n
old table as o
for each statement
mode db2sql
begin atomic
   update test_mqt 
     set cnt = cnt + (select sum(n.a - o.a) 
                        from N join O using(id)
                        where n.a <> o.a
                      );

end@

编辑:MQT的替代方案 我从未在生产中使用过MQT,因为IBM i不支持系统维护的MQT。

在您对更新的聚合感兴趣的场景中,包含聚合的编码矢量索引(EVI)可以提供更好的解决方案;因为它们是自动维护的。

CREATE ENCODED VECTOR INDEX sales_fact_location_id_evi 
ON sales_fact(sale_location_id ASC) 
INCLUDE(SUM(sale_amount_measure))

上面的例子来自文章Accelerated analytics - faster aggregations using the IBM DB2 for i encoded vector index (EVI) technology。这篇文章很好,并将EVI与MQT进行比较以存储聚合。

© www.soinside.com 2019 - 2024. All rights reserved.