Обновление запроса с использованием `CASE WHEN` не работает при срабатывании триггера в PostgreSQL - PullRequest
0 голосов
/ 17 октября 2019

Я пытаюсь использовать условие 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 в утешении. Но обновление не работает.

Этот запрос должен проверять, обновляет ли пользователь поле через веб-интерфейс, только если old.bts_trx_gc <> new.bts_trx_gc. Поскольку это может произойти в веб-интерфейсе, даже если значение bts_trx_gc не изменено, отправляется запрос с bts_trx_gc = Terminé. И я хочу запускать обновление только тогда, когда это поле переходит от чего-то к Terminé.

Учитывая приведенный выше запрос, я пытаюсь сделать, если условие IF верно и old.bts_trx_gc <> new.bts_trx_gcзатем bts_trx_gc = Demandé остальное сохранит то же значение.

Здесь триггерная функция how:

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();

Я хочу научиться этомутак что, если возможно, объясните мне, что я делаю здесь неправильно, или если мой подход не хватает понимания.

1 Ответ

1 голос
/ 17 октября 2019

Я бы использовал IF для условного запуска ОБНОВЛЕНИЯ, а не выражения CASE. Это дает дополнительное преимущество: вы не запускаете ненужные ОБНОВЛЕНИЯ.

Если bts_trx_gc может содержать нулевые значения, вам следует использовать is distinct from вместо <> для правильной обработки значений NULL.

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, чтобы изменить строку в триггере. Используйте триггер 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;
$$;

Но вам нужен триггер ДО, чтобы это сработало:

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();

...