I try to use a CASE WHEN
condition to an update query in PostgreSQL.
The query I am doing is :
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;
The trigger fire every time as I can see the raise info
in the consol. But the update does not work.
This query is to make sure when a user is updating a field through a web interface, the update fire only if old.bts_trx_gc <> new.bts_trx_gc
.
Because it may happens the web interface even if the bts_trx_gc
value is not modified, a query with bts_trx_gc = Terminé
is sent. And I only want to fire the update when this field goes from something to Terminé
only.
Considering the query above, What I am trying to do is if the IF
condition is true and old.bts_trx_gc <> new.bts_trx_gc
then bts_trx_gc = Demandé
else keep same value.
Here the how trigger function :
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;
$$;
And here the trigger :
create trigger after_update_bts_trx_gc
after update
on etude_bts
for each row
execute procedure after_update_bts_trx_gc();
I want to learn from this, so, if possible, explain to me what I'm doing wrong here, or if my approach is lacking insight.
I would use an IF
to conditionally run the UPDATE, not a CASE expression. This has the added benefit, that you don't run unneeded UPDATEs.
If bts_trx_gc
can contain null values you should use is distinct from
rather than <>
to properly deal with NULL values.
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;
$$;
This was my original answer where I overlooked the fact that the UPDATE targeted a different table. I am leaving it for reference though.
Don't use UPDATE to change the row in a trigger. Use a BEFORE UPDATE
trigger and assign the value to the new
row when the condition is met:
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;
$$;
But you need a BEFORE trigger to make that work:
create trigger after_update_bts_trx_gc
BEFORE update
on etude_bts
for each row
execute procedure after_update_bts_trx_gc();
It would be even more efficient to not fire the trigger at all, if the column doesn't change:
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();