【问题标题】:Upsert query not working with null value. how to update with null value in constraints?Upsert 查询不适用于空值。如何在约束中使用空值进行更新?
【发布时间】:2019-07-10 13:49:50
【问题描述】:

我正在使用 pgsql upsert 查询基于三列组合的冲突。这里一列可以为空或不为空,其他两列将始终包含该值。当所有三列都有值时,如果另一列可以为 null 的列没有值,则 Upsert 查询工作(更新值),因此它正在插入记录而不是更新。

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

当我第一次尝试这个查询时,它的插入记录。之后,当我第二次尝试时,它只更新所有 plan_id、module_id、sub_module_id 为 1 的记录。不更新已经插入第三个空值的记录('1'、'2'、null、' 36','36','现在()')。我尝试了很多东西,但没有找到任何方法来做到这一点。我想在第二次执行此查询而不是插入时更新该记录。 如果有人有解决方案,请帮忙。

【问题讨论】:

    标签: sql postgresql upsert


    【解决方案1】:

    在您的唯一约束的上下文中,您有点误解了 NULL 的含义(我假设您已经存在,即使它不在您的 DDL 中)。

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

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

    sub_module_id int4 not null default 0
    

    ...然后为那些没有sub_module_idplan_line_item 行插入一个值0 而不是NULL。因此:

    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 != NULL

    【讨论】:

    • 好的,谢谢汤姆的帮助,我们可以使用这种方式,但我根据 sub_module_id 是否为空做了其他事情。如果我使用这种方式,那么我将不得不根据 sub_module_id 是否为空来更改我所做的那些事情。有没有其他方法可以做到这一点?
    • NULL <> NULLnot 真(但也不是假)。
    猜你喜欢
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多