我在PostgreSQL中的person表上有一个语句触发器,只要更新person表,就会刷新物化视图。其中一列是用于存储从PHP上传的图像的bytea。此列不在物化视图中。每当更新图像列时,人员表上都有一个行触发器来更新图像上载日期列。如果行触发器触发,如何阻止语句触发器触发?
create or replace function person_photo_date_func() returns trigger as $$
begin
new.photo_utc := current_timestamp;
return new;
end;
$$ language plpgsql;
create trigger person_photo_date_tg
after update of photo on person
for each row execute procedure person_photo_date_func();
create or replace function refresh_mv() returns trigger as $$
begin
refresh materialized view vm_csr;
return null;
end
$$ language plpgsql security definer;
create trigger refresh_mat_views_person
after insert or update or delete or truncate
on person for each statement
execute procedure refresh_mv();
答案 0 :(得分:0)
看到这个,有人尝试过这样做,从存储过程https://dba.stackexchange.com/questions/48402/disabling-triggers-in-stored-procedures
中禁用thr触发器我会重新设计这个。你可以使用一些“状态”'您的person_photo_date_func()将在其中放置'交易'要被refresh_mv()跳过。
create table skip_refresh_mv (id serial primary key, xid integer);
create or replace function person_photo_date_func() returns trigger as $$
begin
new.photo_utc := current_timestamp;
INSERT INTO skip_refresh_mv (xid) SELECT txid_current();
return new;
end;
$$ language plpgsql;
create or replace function refresh_mv() returns trigger as $$
begin
IF NOT EXISTS (SELECT 1 FROM skip_refresh_mv WHERE xid = txid_current()) THEN
refresh materialized view vm_csr;
END IF;
return null;
end
$$ language plpgsql security definer;
但它假设每个交易有一个声明
您还需要清除skip_refresh_mv中的旧记录,因此将一些时间戳列添加到skip_refresh_mv表并执行旧记录的例行清理。
如果每个事务最多只有一个这样的语句,那么在检查存在后,您还可以从refresh_mv()
内部清除记录。
P.S。我需要在每个语句中使用pg_stat_activity。 您可以使用以下方式获取当前事务活动查询:
select * from pg_stat_activity where state = 'active' and backend_xid = txid_current()::integer;