Ошибка запуска PSQL и пары функций при ВСТАВКЕ

#postgresql #triggers #sql-insert #plpgsql

#postgresql #триггеры #sql-вставка #plpgsql

Вопрос:

У меня есть таблица ( time TIMESTAMP PRIMARY KEY, pressure REAL NOT NULL ). Мне нужно разработать пару триггер / функция, которая делает это: при вставке новой записи либо обновите существующую запись, либо вставьте новую запись в зависимости от метки времени.

Код триггера:

 CREATE TRIGGER trigger_insert
    BEFORE INSERT ON mytable
    FOR EACH ROW
    EXECUTE PROCEDURE func_insert();
  

Метод функции:

 create or replace function func_insert()
returns trigger
language plpgsql
as
$$
DECLARE
    time_exists TIMESTAMP;
    BEGIN
        IF pg_trigger_depth() <> 1 THEN
            RETURN NEW;
        END IF;
        SELECT time INTO time_exists FROM mytable WHERE time = NEW.time;
    IF NOT FOUND THEN
        INSERT INTO mytable VALUES(NEW.*);
    ELSE 
        UPDATE mytable SET pressure = NEW.pressure WHERE time = NEW.time;
    END IF;
    RETURN NEW;
END;
$$;
  

Обсуждение:

  1. Без IF pg_trigger_depth() <> 1 THEN условия сценарий приводит к исключению переполнения триггера глубины.

  2. Проблема в том, что я получаю ошибку при вставке первой (sic!) записи в пустую (sic!) таблицу:

    psycopg2.ошибки.Уникальное нарушение: повторяющееся значение ключа нарушает уникальное ограничение «mytable_key» ПОДРОБНО: Ключ («время»)=(2019-06-01 00:00:00) уже существует.

Спасибо.

Ответ №1:

Если строка должна быть вставлена, просто верните new вместо того, чтобы пытаться вставить ее снова.

Если строка должна быть обновлена, не возвращайте, new иначе она будет вставлена…

При этом выполнение upsert является самым чистым решением

 INSERT INTO myTable (time, pressure) VALUES (..., ...)
  ON CONFLICT (time)
    DO UPDATE SET pressure = EXCLUDED.pressure;