Можно ли проверить только часть первичного ключа в postgres при использовании В КОНФЛИКТЕ

#sql #postgresql #upsert

Вопрос:

Есть столик в постгресе

 attr_id uuid not null,
item_id uuid not null,
common_value varchar(100) not null,
int_value int,
primary key(attr_id, item_id, common_value)
 

Может иметь 2 типа вставок: один, когда значение int_ может отличаться для пары attr_id-item_id, и один, когда должно быть одно значение для значения int_ для пары attr_id-item_id

Поэтому я хочу проверить их на наличие конфликтов вот так

 On Conflict (attr_id, item_id, common_value) for multiple values
On Conflict (attr_id, item_id) for single value
 

Конечно, это не работает для одного значения с первичным ключом(attr_id, item_id, common_value) )))

Есть ли какой-либо способ добиться этого с помощью индексов или ограничений, которые могут быть, или любым другим способом, кроме разделения таблицы на 2?

Заранее спасибо за ответы 😉

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

1. Нет, это невозможно. on conflict() Предложение должно либо ссылаться на уникальное ограничение по имени, либо на все столбцы уникального ограничения

Ответ №1:

Один мой друг предложил решение.

добавить столбец

 is_single bool default false
 

затем создайте индекс, подобный этому

 create unique index single_idx on table_name(attr_id, item_id) where is_single;
 

а затем мы меняемся (в случае конфликта) на одно значение, подобное этому:

 OnConflict("(attr_id, item_id) where is_single DO UPDATE")
 

И это сработало. Тесты прошли без проблем. Никаких ошибок, никаких дубликатов для нескольких значений и одиночных значений, изменяющихся так, как они должны