PostgreSQL: проверка на NEW и OLD в функции для триггера

Я хочу создать триггер, который считает строки и обновляет поле в другой таблице. Мое текущее решение работает для операторов INSERT, но не удается, когда я удаляю строку.

Моя текущая функция:

 CREATE OR REPLACE FUNCTION update_table_count()
RETURNS trigger AS
$$
DECLARE updatecount INT;
  BEGIN
      Select count(*) into updatecount 
        From source_table 
       Where id = new.id;
      Update dest_table set count=updatecount 
       Where id = new.id;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

Триггер довольно простой, выглядит как.

CREATE TRIGGER count_trigger
AFTER INSERT OR DELETE
ON source_table
FOR EACH ROW
EXECUTE PROCEDURE update_table_count();

Когда я выполняю инструкцию DELETE, возникает следующая ошибка:

ОШИБКА: запись "новая" еще не назначена

ДЕТАЛИ: структура кортежа еще не назначенной записи является неопределенной.

Я знаю, что одним из решений может быть создание только одного набора триггеров и функций для DELETE и одного для оператора INSERT. Но я хочу сделать это более элегантно и узнать, есть ли решение, чтобы проверить, присутствует ли NEW или OLD в текущем контексте, и просто реализовать блок IF ELSE. Но я не знаю, как проверить этот контекст чувствительных элементов.

Спасибо за вашу помощь

2 ответа

Решение

Обычный подход к выполнению функции триггера в зависимости от того, как сработал триггер, заключается в проверке операции триггера через TG_OP.

CREATE OR REPLACE FUNCTION update_table_count()
RETURNS trigger AS
$$
DECLARE 
  updatecount INT;
BEGIN
  if tg_op = 'UPDATE' then 
    select count(*) into updatecount from source_table where id = new.id;
    update dest_table set count=updatecount where id = new.id;
  elsif tg_op = 'DELETE' then 
    ... do something else
  end if;
  RETURN NEW;
END;
$$
LANGUAGE plpgsql;

Не связано, но: название языка является идентификатором. Не цитируйте его, используя одинарные кавычки.

From PostgreSQL's documentation:

NEW

Data type RECORD; variable holding the new database row for INSERT/UPDATE operations in row-level triggers. This variable is null in statement-level triggers and for DELETE operations.

OLD

Data type RECORD; variable holding the old database row for UPDATE/DELETE operations in row-level triggers. This variable is null in statement-level triggers and for INSERT operations.

So, for example, if NEW is NULL, then the trigger was invoked on DELETE.

Другие вопросы по тегам