psycopg2.NotSupportedError: предложение INSERT with ON CONFLICT не может быть использовано с таблицей, имеющей правила ВСТАВКИ или ОБНОВЛЕНИЯ

#database #postgresql #rules #insert-update

#База данных #postgresql #Правила #вставить-обновить

Вопрос:

Когда я создаю ПРАВИЛО обновления рядом с предложением CONFLICT, возникает эта ошибка.

Вот мой код конфликта

  insert_query = "INSERT INTO my_company (id, name, login, logout) VALUES %s
                    ON CONFLICT (id) DO NOTHING"
  

мое ПРАВИЛО обновления

 CREATE RULE log_shoelace AS ON UPDATE TO my_company
    WHERE NEW.login <> OLD.login or NEW.logout <> OLD.logout
    DO INSERT INTO my_company VALUES (
    new.id, new.name, new.login, new.logout, new.interval_time, current_date);
  

поле таблицы my_company содержит идентификатор, имя, логин. выход из системы, interval_time, сегодня.

если какие-либо данные обновлены, вставьте эти данные в ту же таблицу. Но здесь я не могу использовать CONFLICT и RULE одновременно. Итак, что я могу сделать в этом случае?

Спасибо.

Создание таблицы и последовательности для тестирования:

 CREATE SEQUENCE IF NOT EXISTS my_company_id_seq;

CREATE TABLE public.my_company
( id            integer NOT NULL DEFAULT nextval('my_company_id_seq'::regclass)
, name          character varying(50)
, login         time without time zone
, logout        time without time zone
, interval_time time without time zone
, today         date DEFAULT CURRENT_DATE
, CONSTRAINT my_company_pkey PRIMARY KEY (id) 
);
  

Комментарии:

1. Вы хотите вставить при конфликте или обновить при конфликте? Похоже, вы пытаетесь сделать INSERT ... ON CONFLICT DO UPDATE . Мне кажется, что вам вообще не нужно правило. Какие типы данных для login и logout ? Если они есть timestamp , маловероятно, что они когда-либо будут равны.

2. вход и выход из системы относятся к типу данных TIME

3. мой конфликт связан с insert, а правило — с update

4. но без создания ПРАВИЛА, как я могу вставить данные в поля today, когда что-то будет обновлено?

5. Взгляните на этот SQLFiddle и дайте мне знать, если вы все еще считаете, что вам нужно RULE : sqlfiddle.com /#!17/073e9/16 . Если я чего-то не упустил, вы получите те же результаты, используя INSERT ... ON CONFLICT UPDATE . За исключением случаев, когда ваш RULE сбой произойдет из-за нарушения дубликата ключа.

Ответ №1:

ON CONFLICT Директива должна содержаться в теле вашего правила:

 CREATE RULE log_shoelace AS 
    ON UPDATE TO my_company
        WHERE NEW.login <> OLD.login or NEW.logout <> OLD.logout
    DO 
        INSERT INTO my_company VALUES (
            new.id, new.name, new.login, new.logout, new.interval_time, current_date)
    ON CONFLICT (id) DO NOTHING
  

Хорошо сказать, ON CONFLICT директивы работают только тогда, когда целевая таблица имеет некоторое ограничение для отсрочки конфликта. В противном случае у вас будут ошибки во время выполнения, такие как:

 No unique or exclusion constraint matching the ON CONFLICT specification.