Как правильно выполнить обновление в postgres 9.5

правильный синтаксис upsert с postgresql 9.5, ниже запрос показывает ошибку column reference "gallery_id" is ambiguous, почему?

var dbQuery = `INSERT INTO category_gallery (
  category_id, gallery_id, create_date, create_by_user_id
  ) VALUES ($1, $2, $3, $4)
  ON CONFLICT (category_id)
  DO UPDATE SET
  category_id = $1,
  last_modified_date = $3,
  last_modified_by_user_id = $4
  WHERE gallery_id = $2`;

Я попробовал изменить WHERE gallery_id = $2; на WHERE category_gallery.gallery_id = $2;, а затем показывает ошибку there is no unique or exclusion constraint matching the ON CONFLICT specification, но Я не хочу, чтобы set_file или category_id были уникальными, потому что я хочу, чтобы оба столбца были такими же, обновить....

Как правильно выполнить upsert в postgres 9.5?

if ON CONFLICT нужен уникальный столбец, следует ли использовать другой метод, как?



Я хочу, чтобы несколько столбцов обоих конфликтов затем обновлялись, что правильно используется

var dbQuery = `INSERT INTO category_gallery (
  category_id, gallery_id, create_date, create_by_user_id
  ) VALUES ($1, $2, $3, $4)
  ON CONFLICT (category_id, gallery_id)
  DO UPDATE SET
  category_id = $1,
  last_modified_date = $3,
  last_modified_by_user_id = $4
  WHERE gallery_id = $2`;


var dbQuery = `INSERT INTO category_gallery (
  category_id, gallery_id, create_date, create_by_user_id
  ) VALUES ($1, $2, $3, $4)
  ON CONFLICT (category_id AND gallery_id)
  DO UPDATE SET
  category_id = $1,
  last_modified_date = $3,
  last_modified_by_user_id = $4
  WHERE gallery_id = $2`;

table (category_id, gallery_id не уникальный столбец)

category_id | gallery_id | create_date | create_by_user_id | last_modified_date | last_modified_by_user_id
1 | 1 | ...  
1 | 2 | ...
2 | 2 | ...
1 | 3 | ...

Ответ 1

Конструкция ON CONFLICT требует ограничения UNIQUE. Из документации по INSERT .. ON CONFLICT статья:

Необязательное предложение ON CONFLICT указывает альтернативное действие для повышения ошибки нарушения уникальное нарушение или исключения ограничения. Для каждой отдельной строки, предложенной для вставки, либо вставка продолжается, либо, если нарушено ограничение или указатель арбитра, указанное в конфликте_target, выполняется альтернативное конфликтное действие. ON CONFLICT DO NOTHING просто избегает вставки строки в качестве ее альтернативного действия. ON CONFLICT DO UPDATE обновляет существующую строку, которая конфликтует со строкой, предложенной для вставки, в качестве ее альтернативного действия.

Теперь вопрос не очень ясен, но вам, вероятно, понадобится ограничение UNIQUE для двух столбцов: (category_id, gallery_id).

ALTER TABLE category_gallery
    ADD CONSTRAINT category_gallery_uq
    UNIQUE (category_id, gallery_id) ;

Если строка, которую нужно вставить, соответствует и значениям со строкой, уже указанной в таблице, вместо INSERT выполните UPDATE:

INSERT INTO category_gallery (
  category_id, gallery_id, create_date, create_by_user_id
  ) VALUES ($1, $2, $3, $4)
  ON CONFLICT (category_id, gallery_id)
  DO UPDATE SET
    last_modified_date = EXCLUDED.create_date,
    last_modified_by_user_id = EXCLUDED.create_by_user_id ;

Вы можете использовать либо столбцы ограничения UNIQUE:

  ON CONFLICT (category_id, gallery_id) 

или имя ограничения:

  ON CONFLICT ON CONSTRAINT category_gallery_uq  

Ответ 2

Как упрощенная альтернатива принятому в настоящее время ответе, ограничение UNIQUE может быть анонимно добавлено при создании таблицы:

CREATE TABLE table_name (
    id  TEXT PRIMARY KEY,
    col TEXT,
    UNIQUE (id, col)
);

Затем выполняется запрос upsert (аналогично тому, что уже было сказано):

INSERT INTO table_name (id, col) VALUES ($1, $2)
ON CONFLICT (id, col)
    DO UPDATE SET col = $2;