2017-10-13 3 views
1

私が持っているテーブルにアップサートをやろうとしている部分一意索引平野に関しては PostgreSQLの部分ユニークインデックスとアップサート

create table test (
    p text not null, 
    q text, 
    r text, 
    txt text, 
    unique(p,q,r) 
); 

create unique index test_p_idx on test(p) where q is null and r is null; 
create unique index test_pq_idx on test(p, q) where r IS NULL; 
create unique index test_pr_idx on test(p, r) where q is NULL; 

pはないnullで、唯一 qの一つまたは r nullにすることができます。しかし
insert into test(p,q,r,txt) values ('p',null,null,'a'); -- violates test_p_idx 
insert into test(p,q,r,txt) values ('p','q',null,'b'); -- violates test_pq_idx 
insert into test(p,q,r,txt) values ('p',null, 'r','c'); -- violates test_pr_idx 

を予想通り、私はそれはまだ制約違反をスロー

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

アップサートのためのユニーク制約を使用しようとしているとき

重複インサートは、制約違反をスロー

しかし、私はon conflict句を期待したいoそれをキャッチし、更新を行います。

私は間違っていますか? index_predicateを使用する必要がありますか?

index_predicate Used to allow inference of partial unique indexes. Any indexes that satisfy the predicate (which need not actually be partial indexes) can be inferred. Follows CREATE INDEX format. https://www.postgresql.org/docs/9.5/static/sql-insert.html

+0

https://stackoverflow.com/a/46728249/330315のPostgresにアップサートを実行している間ON CONFLICT句で使用されていない[部分インデックスの –

+0

可能な複製ql](https://stackoverflow.com/questions/46727740/partial-index-not-used-in-on-conflict-clause-while-performing-an-upsert-in-postg) – Eelke

答えて

2

複数の部分インデックスを競合ターゲットとして使用することはできません。単一のインデックスを使用して、望ましい動作を達成しようとする必要があります。あなたが渡す必要がありinsertコマンドで

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 

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, '')); 

今すぐ(2回実行)3つのテストすべてが同じインデックスに違反:私が見ることができる唯一の方法は、式に一意索引を使用することですインデックスの定義で使用される式:

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; 
関連する問題