двойное значение ключа нарушает уникальное ограничение на конфликт не работает - PullRequest
0 голосов
/ 28 января 2019

Я пытаюсь использовать в конфликте с уникальным на нескольких полях.У меня есть эта структура.

|---------------------|------------------|
|      id             |     uuid         |
|---------------------|------------------|
|      name           |     string       |
|---------------------|------------------|
|      field_a        |     uuid         |
|---------------------|------------------|
|      field_b        |     uuid         |
|---------------------|------------------|
|      field_c        |     uuid         |
|---------------------|------------------|

field_a,field_b,field_c являются уникальными и field_b может быть NULL.

Это мой запрос:

INSERT INTO table (field_a, field_b,field_c,  name) 
values ('434d1d67-df03-4310-b3eb-93bf1c6e319e',
        'd3a3745e-ad97-4fcd-1fed-26bb406dc265',
        'd5a4232e-ad56-6ecd-5fed-25bb106dc114')
on conflict(field_a,field_b,field_c) 
do update
  set  name = 'abc'

Если я попытаюсьэто с тем же запросом снова это работает.Это обновляет информацию о конфликте.Но когда я использую нуль, как это:

INSERT INTO 
table (field_a, field_b,field_c,  name) 
values ('434d1d67-df03-4310-b3eb-93bf1c6e319e',
        null,
        'd5a4232e-ad56-6ecd-5fed-25bb106dc114')
on conflict(field_a,field_b,field_c) 
do update
set  name = 'abc'

Это не работает.Это добавит новую строку в мою таблицу.Чтобы предотвратить добавление новой строки, я создал индекс и установил значения NULL, как это

CREATE 
UNIQUE INDEX uidx_uniq ON table USING btree (
   (COALESCE(field_a, '00000000-0000-0000-0000-000000000000'::uuid)),
   (COALESCE(field_a, '00000000-0000-0000-0000-000000000000'::uuid)),
   (COALESCE(field_a, '00000000-0000-0000-0000-000000000000'::uuid)))

Это не позволяет добавлять новое значение в БД, если какое-либо существует с нулем, но при конфликте не работает с этим, это дает мне ошибку:

duplicate key value violates unique constraint "uidx_uniq"

Как я могу решить это с нулем?

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Я думаю, вам также нужен отфильтрованный уникальный индекс:

CREATE UNIQUE INDEX uidx_uniq2 ON table (field_a, field_c)
    WHERE field_b IS NULL;

Вам нужно будет проверить оба индекса на наличие конфликтов в ON CONFLICT.

0 голосов
/ 28 января 2019

Поскольку документация гласит:

Нулевые значения не считаются равными.

Таким образом, нет конфликта, если одно из значенийNULL.

Вы не можете использовать уникальный индекс, который вы создали с помощью предложения ON CONFLICT, потому что вы можете использовать только уникальные ограничения .Уникальные ограничения не могут быть определены для выражений, только для столбцов.

Возможно, вам следует использовать другое значение, отличное от NULL, чтобы смоделировать то, что вы имеете в виду.NULL означает «неизвестный» в SQL, поэтому интерпретация PostgreSQL имеет смысл.

...