具有 2 个唯一约束的 Postgres upsert

时间:2021-06-21 23:30:50

标签: postgresql sql-insert upsert unique-index

我有一个包含 2 个唯一索引的表,以允许其中一列中的空值。

df$time

A) 我可以在提供 delivery_date 时执行更新插入吗?

CREATE TABLE public.pairs_dup
(
    id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
    base integer NOT NULL,
    quote integer NOT NULL,
    delivery_date timestamp with time zone,
    data float,
    CONSTRAINT pairs_dup_pkey PRIMARY KEY (id)
)

CREATE UNIQUE INDEX pairs_dup_not_null_idx
    ON public.pairs_dup USING btree
    (base ASC NULLS LAST, quote ASC NULLS LAST, delivery_date ASC NULLS LAST)
    WHERE delivery_date IS NOT NULL;

CREATE UNIQUE INDEX pairs_dup_null_idx
    ON public.pairs_dup USING btree
    (base ASC NULLS LAST, quote ASC NULLS LAST)
    WHERE delivery_date IS NULL;

B) 我可以在不提供交货日期的情况下执行 upsert 吗?

INSERT INTO pairs_dup(base, quote, delivery_date, data) values ('A', 'B', '2016-06-22 19:10:25-07', 0.5)
ON CONFLICT (base, quote, delivery_date) DO UPDATE SET data = 0.5;

1 个答案:

答案 0 :(得分:1)

Ad A):是的,但 ON CONFLICT 子句需要包含索引谓词:

INSERT INTO pairs_dup(base, quote, delivery_date, data)
   VALUES (42, 4711, '2016-06-22 19:10:25-07', 0.5)
ON CONFLICT (base, quote, delivery_date)
   WHERE delivery_date IS NOT NULL  /* this is essential */
   DO UPDATE SET data = 0.5;

正如the documentation所说:

<块引用>

index_predicate

用于允许推断部分唯一索引。可以推断出满足谓词的任何索引(实际上不必是部分索引)。

广告 B):同样,您必须在 WHERE delivery_date IS NULL 子句中添加 ON CONFLICT

添加这些子句似乎是多余的,但它是必需的,以便可以推断出部分索引。