postgresql - 在 PostgreSQL 中触发触发器时,使用“CASE WHEN”更新查询不起作用
问题描述
我尝试CASE WHEN
在 PostgreSQL 中对更新查询使用条件。
我正在做的查询是:
if new.bts_trx_gc = 'Terminé' then
update stt set stt_doe_gc_bts = (case when old.bts_trx_gc <> new.bts_trx_gc then 'Demandé' else stt_doe_gc_bts end) where stt_id = new.bts_id;
raise info 'test est un test';
end if;
正如我在控制台中看到的那样,触发器每次都会触发raise info
。但是更新不起作用。
此查询是为了确保当用户通过 Web 界面更新字段时,更新仅在old.bts_trx_gc <> new.bts_trx_gc
. 因为即使bts_trx_gc
没有修改值也可能会出现在 Web 界面上,所以bts_trx_gc = Terminé
会发送一个查询。而且我只想在此字段从某事变为Terminé
唯一时触发更新。
考虑到上面的查询,我想做的是如果IF
条件为真,old.bts_trx_gc <> new.bts_trx_gc
否则bts_trx_gc = Demandé
保持相同的值。
这里是如何触发功能:
create or replace function after_update_bts_trx_gc() returns trigger
language plpgsql
as
$$
begin
if new.bts_trx_gc = 'Terminé' then
update stt set stt_doe_gc_bts = (case when old.bts_trx_gc <> new.bts_trx_gc then 'Demandé' else stt_doe_gc_bts end) where stt_id = new.bts_id;
raise info 'test est un test';
end if;
return new;
end;
$$;
这里是触发器:
create trigger after_update_bts_trx_gc
after update
on etude_bts
for each row
execute procedure after_update_bts_trx_gc();
我想从中吸取教训,所以,如果可能的话,向我解释我在这里做错了什么,或者我的方法是否缺乏洞察力。
解决方案
我会使用 anIF
有条件地运行 UPDATE,而不是 CASE 表达式。这有一个额外的好处,即您不会运行不需要的更新。
如果bts_trx_gc
可以包含空值,您应该使用is distinct from
而不是<>
正确处理空值。
create or replace function after_update_bts_trx_gc() returns trigger
language plpgsql
as
$$
begin
if new.bts_trx_gc = 'Terminé' and old.bts_trx_gc IS DISTINCT FROM new.bts_trx_gc then
UPDATE stt
set stt_doe_gc_bts = 'Demandé'
WHERE stt_id = new.bts_id;
raise info 'test est un test';
end if;
return new;
end;
$$;
这是我最初的答案,我忽略了 UPDATE 针对不同表的事实。不过,我将其留作参考。
不要使用 UPDATE 来更改触发器中的行。使用触发器并在满足条件时BEFORE UPDATE
将值分配给行:new
create or replace function after_update_bts_trx_gc() returns trigger
language plpgsql
as
$$
begin
if new.bts_trx_gc = 'Terminé' and old.bts_trx_gc <> new.bts_trx_gc then
new.stt_doe_gc_bts := 'Demandé';
raise info 'test est un test';
end if;
return new;
end;
$$;
但是您需要一个 BEFORE 触发器才能使其工作:
create trigger after_update_bts_trx_gc
BEFORE update
on etude_bts
for each row
execute procedure after_update_bts_trx_gc();
如果列没有改变,那么根本不触发触发器会更有效:
create trigger after_update_bts_trx_gc
BEFORE update
on etude_bts
for each row
when (old.bts_trx_gc <> new.bts_trx_gc)
execute procedure after_update_bts_trx_gc();
推荐阅读
- react-native - 如何从数组中获取组件并在 react native 中更改其道具?
- kubernetes - 有没有办法通过字符串值过滤指标,其中一部分来自普罗米修斯查询中另一个查询的结果?
- cesium - 铯负载gltf不是正确的位置
- html - 如何将类选择器应用于元素?
- jenkins - 我可以访问 Jenkins 管道中的当前阶段 id 吗?
- ruby-on-rails - Rails Active Storage 不显示 @user.banner_image
- angular - 我怎样才能使 devextreme dx-autocomplete 仅成为数字
- javascript - 引导模式不加载图像
- javascript - 是否有任何解决方法(或破解)可以在 Chrome、Firefox 和 Safari 上自动播放音频?
- python - 在读取和执行操作时写入 CSV 文件时未写入数据