在Postgresql中我可以有两种触发器:FOR EACH ROW和FOR EACH STATEMENT。如果我执行FOR EACH ROW触发器,我可以添加类似OLD.* != NEW.*
的WHERE子句,因此只有在实际发生了某些变化时它才会触发。有没有办法用STATEMENT级触发器做类似的事情?我知道我不能做同样的事情,因为OLD和NEW都不可用,但我想也许有办法检查我的函数本身或类似内容中更改的行数。 / p>
用法案例:我正在使用postgresql NOTIFY系统在数据发生变化时通知我的应用。理想情况下,每当一个或更多记录发生更改时,应用程序就会收到一条通知,如果数据保持不变(即使运行了UPDATE),也不会得到通知。对于每个语句的基本AFTER UPDATE触发器,每次更新语句运行时我都会收到通知 - 即使它实际上没有更改任何内容。
答案 0 :(得分:2)
您应该创建两个触发器:before update for each row
和after update for each statement
。
第一个触发器检查表是否正在更新,如果是,则设置标志。
第二个触发器检查标志并执行notify
(如果已设置)。
您可以使用自定义配置参数作为标记(例如flags.the_table
)。
解决方案简单而安全,因为参数在当前会话中是本地的。
create or replace function before_each_row_on_the_table()
returns trigger language plpgsql
as $$
begin
if new <> old then
set flags.the_table to 'on';
end if;
return new;
end $$;
create or replace function after_each_statement_on_the_table()
returns trigger language plpgsql
as $$
begin
if (select current_setting('flags.the_table')) = 'on' then
notify your_channel, 'the_table was updated';
set flags.the_table to 'off';
end if;
return null;
exception
when undefined_object then
-- occurs when flags.the_table was not defined
return null;
end $$;
create trigger before_each_row_on_the_table
before update on the_table
for each row execute procedure before_each_row_on_the_table();
create trigger after_each_statement_on_the_table
after update on the_table
for each statement execute procedure after_each_statement_on_the_table();