我正在尝试在多个字段上使用唯一性冲突。我有这个结构。
|---------------------|------------------|
| 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'
如果我再次使用相同的查询尝试此操作,它将起作用。它在冲突时更新。但是当我像这样使用null时:
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)))
这不允许在db中添加新值(如果存在的任何值为null的情况下),但是在冲突下无法使用它,这会给我错误:
duplicate key value violates unique constraint "uidx_uniq"
如何用null来解决这个问题?
答案 0 :(得分:0)
空值不视为相等。
因此,如果值之一为NULL,则不会发生冲突。
您不能使用通过ON CONFLICT
子句创建的唯一索引,因为您只能在其中使用唯一的约束。不能在表达式上定义唯一约束,只能在列上定义。
也许您应该使用一个不同的NULL值,以便对您的意思进行建模。 NULL在SQL中表示“未知”,因此PostgreSQL的解释是有道理的。
答案 1 :(得分:0)
我认为您还需要过滤的唯一索引:
CREATE UNIQUE INDEX uidx_uniq2 ON table (field_a, field_c)
WHERE field_b IS NULL;
您需要检查两个索引中ON CONFLICT
中是否存在冲突。