Postgresql:仅当数据发生更改时,才在更新每个语句之后运行触发器

wljmcqd8  于 2023-01-25  发布在  PostgreSQL
关注(0)|答案(1)|浏览(256)

在Postgresql中,我可以有两种触发器:FOR EACH ROW和FOR EACH STATEMENT。如果我使用FOR EACH ROW触发器,我可以添加一个WHERE子句,类似于OLD.* != NEW.*,这样它只在实际发生更改时才触发。有没有办法对STATEMENT级别的触发器执行类似操作?我知道我无法执行相同操作,因为OLD和NEW不可用。但我在想,也许有一种方法可以检查在函数本身或类似的地方更改的行数。
使用案例:我正在使用postgresql NOTIFY系统来通知我的应用程序数据发生了变化。理想情况下,应用程序会在每次一条或多条记录发生变化时收到一个通知,如果数据保持不变,则根本不会收到通知(即使运行了UPDATE)。使用基本的AFTER UPDATE FOR EACH STATEMENT触发器,每次运行update语句时,我都会收到通知--即使它实际上没有改变任何东西。

nuypyhwy

nuypyhwy1#

应创建两个触发器:before update for each rowafter update for each statement
第一触发器检查表是否正在被更新,如果是,则设置标志。
第二个触发器检查标志,如果设置了notify,则执行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 current_setting('flags.the_table', true) = 'on' then
        notify your_channel, 'the_table was updated';
        set flags.the_table to 'off';
    end if;
    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();

带两个参数的函数current_setting()在Postgres 9.6或更高版本中可用。

相关问题