Upsert查询不适用于null值。如何在约束中使用空值更新?

时间:2019-02-16 17:43:33

标签: sql postgresql upsert

我在基于三列组合的冲突上使用pgsql upsert查询。此处一列可以为null,也可以为null,其他两列将始终包含该值。如果其他三个可以为空的列都没有值,则当所有三个列都具有值时更新查询工作(更新值)。

CREATE TABLE "public"."plan_line_items" (
    "plan_id" int4 NOT NULL
    "module_id" int4 NOT NULL,
    "sub_module_id" int4,
    "created_date" timestamptz(6) NOT NULL DEFAULT now(),
    "modified_date" timestamptz(6) NOT NULL DEFAULT now(),
    "created_by" int4 NOT NULL,
    "modified_by" int4 NOT NULL,
    "is_active" bool NOT NULL DEFAULT true,
);

INSERT INTO plan_line_items1 ( plan_id,module_id, sub_module_id, created_by, modified_by, modified_date )
VALUES ( '1', '1', '1', '36', '36', 'now()' ),
( '1', '2', null, '36', '36', 'now()' ) ON CONFLICT ( 
plan_id,module_id,sub_module_id ) DO UPDATE SET modified_by = EXCLUDED.modified_by,
modified_date = EXCLUDED.modified_date

当我第一次尝试此查询时,将其插入记录。之后,当我第二次尝试时,它仅更新具有1的所有plan_id,module_id,sub_module_id的记录。不更新已经插入了第三个null值(“ 1”,“ 2”,null,“ 36','36','now()')。我尝试了很多事情,但没有找到任何方法可以做到这一点。我想在第二次执行此查询而不是插入时更新该记录。 如果有人有解决方案,请帮忙。

1 个答案:

答案 0 :(得分:0)

在您唯一约束的上下文中,您在某种程度上误解了NULL的含义(即使您的DDL中不存在,我也假设您已经存在)。

sub_module_id的值为NULL并不意味着“此plan_line_item没有sub_module_id”,而是“我们不知道此plan_line_item是否有一个sub_module_id”。这就是为什么它在您的唯一约束中无法按预期工作的原因。

我建议将sub_module_id列的数据类型更改为:

sub_module_id int4 not null default 0

...,然后为没有0的{​​{1}}行插入NULL而不是plan_line_item的值。因此:

sub_module_id

或者,换句话说:CREATE TABLE regt.plan_line_items ( plan_id int4 NOT null, module_id int4 NOT NULL, sub_module_id int4 not null default 0, created_date timestamptz(6) NOT NULL DEFAULT now(), modified_date timestamptz(6) NOT NULL DEFAULT now(), created_by int4 NOT NULL, modified_by int4 NOT NULL, is_active bool NOT NULL DEFAULT true, unique (plan_id,module_id,sub_module_id) ); INSERT INTO regt.plan_line_items ( plan_id,module_id, sub_module_id, created_by, modified_by, modified_date ) VALUES ( '1', '1', '1', '36', '36', 'now()' ), ( '1', '2', '0', '36', '36', 'now()' ) ON CONFLICT ( plan_id,module_id,sub_module_id ) DO UPDATE SET modified_by = EXCLUDED.modified_by, modified_date = EXCLUDED.modified_date; != NULL