PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Index unique partiel PostgreSQL et upsert

Je ne pense pas qu'il soit possible d'utiliser plusieurs index partiels comme cible de conflit. Vous devriez essayer d'obtenir le comportement souhaité en utilisant un seul index. La seule façon que je peux voir est d'utiliser un index unique sur les expressions :

drop table if exists test;
create table test (
    p text not null,
    q text,
    r text,
    txt text
);

create unique index test_unique_idx on test (p, coalesce(q, ''), coalesce(r, ''));

Désormais, les trois tests (exécutés deux fois) violent le même index :

insert into test(p,q,r,txt) values ('p',null,null,'a'); -- violates test_unique_idx
insert into test(p,q,r,txt) values ('p','q',null,'b');  -- violates test_unique_idx
insert into test(p,q,r,txt) values ('p',null, 'r','c'); -- violates test_unique_idx

Dans la commande d'insertion, vous devez passer les expressions utilisées dans la définition de l'index :

insert into test as u (p,q,r,txt) 
values ('p',null,'r','d') 
on conflict (p, coalesce(q, ''), coalesce(r, '')) do update 
set txt = excluded.txt;