Как правильно выполнить обновление в 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;