Postgres 9.5の新しいUPSERT機能の使用に問題があります
別のテーブルからデータを集計するために使用されるテーブルがあります。複合キーは20列で構成され、そのうち10列はNULL可能です。以下に、特にNULL値を使用して、私が抱えている問題のより小さなバージョンを作成しました。
CREATE TABLE public.test_upsert (
upsert_id serial,
name character varying(32) NOT NULL,
status integer NOT NULL,
test_field text,
identifier character varying(255),
count integer,
CONSTRAINT upsert_id_pkey PRIMARY KEY (upsert_id),
CONSTRAINT test_upsert_name_status_test_field_key UNIQUE (name, status, test_field)
);
このクエリの実行は、必要に応じて機能します(最初の挿入、その後の挿入は単純にカウントを増やします)。
INSERT INTO test_upsert as tu(name,status,test_field,identifier, count)
VALUES ('shaun',1,'test value','ident', 1)
ON CONFLICT (name,status,test_field) DO UPDATE set count = tu.count + 1
where tu.name = 'shaun' AND tu.status = 1 AND tu.test_field = 'test value';
ただし、このクエリを実行すると、最初の行のカウントを増やすのではなく、毎回1行が挿入されます。
INSERT INTO test_upsert as tu(name,status,test_field,identifier, count)
VALUES ('shaun',1,null,'ident', 1)
ON CONFLICT (name,status,test_field) DO UPDATE set count = tu.count + 1
where tu.name = 'shaun' AND tu.status = 1 AND tu.test_field = null;
これが私の問題です。カウント値を単純にインクリメントする必要があり、NULL値を持つ複数の同一行を作成する必要はありません。
部分的な一意のインデックスを追加しようとしています:
CREATE UNIQUE INDEX test_upsert_upsert_id_idx
ON public.test_upsert
USING btree
(name COLLATE pg_catalog."default", status, test_field, identifier);
ただし、これにより同じ結果が得られます。複数のnull行が挿入されるか、挿入しようとしたときにこのエラーメッセージが表示されます。
エラー:ON CONFLICT仕様に一致する一意性制約または除外制約はありません
私はすでにのような部分インデックスに追加の詳細を追加しようとしましたWHERE test_field is not null OR identifier is not null
。ただし、挿入すると制約エラーメッセージが表示されます。
count = CASE WHEN EXCLUDED.count IS NULL THEN tu.count ELSE COALESCE(tu.count, 0) + COALESCE(EXCLUDED.count, 0) END
単純化することができるcount = COALESCE(tu.count+EXCLUDED.count, EXCLUDED.count, tu.count)