UPDATE ON CONFLICT 查询时违反 NOT NULL 约束

问题描述 投票:0回答:1

我有一个表

player
,其中包含以下 DDL。我只更改了列名称和顺序:

create table if not exists player (
    id varchar primary key,
    col1 boolean not null default false,
    col2 json not null default '{}',
    col3 varchar not null,
    col4 varchar not null,
    col5 json not null default '{}',
    col6 boolean not null default false
);

这是我尝试运行的查询:

insert into player(id, col1, col2)
values (val_id, val1, val2)
on conflict(id)
do update set col1=excluded.col1, col2=excluded.col2

(存在具有相同

id
的另一行,因此应该会发生
UPDATE
。)

col3
NOT NULL
约束。 (我在查询之前验证了它有一个值。)然而,当查询运行时,Postgres 告诉我:

错误:...关系“player”的“col3”列中的空值违反了非空约束

我检查了 Postgres 文档,但找不到查询有什么问题。可能是什么问题?

sql postgresql database-design null upsert
1个回答
0
投票

TL;博士

如果

col3
定义为
NOT NULL
而没有默认值,则
INSERT
必须 为其提供非空值。

深入

首先检查

NOT NULL
约束。 说明书:

当一个表有多个

CHECK
约束时,将对它们进行测试 每行按名称字母顺序排列,检查后
NOT NULL
限制

我的粗体强调。
可能尝试用普通的

NOT NULL
约束替换
CHECK
说明书:

非空约束总是写为列约束。 A 非空约束在功能上等同于创建检查 约束

CHECK
(
column_name IS NOT NULL
),但在 PostgreSQL 中 创建显式非空约束更加有效。这 缺点是你不能给 not-null 指定明确的名称 以这种方式创建的约束。

但是无济于事。任一约束都会立即检查,并且不能推迟。 说明书:

NOT NULL
CHECK
约束总是立即检查
插入或修改一行(不在语句末尾)。

我的粗体强调。
这是核心问题。

执行以下操作之一来解决:

  1. col3
    定义非空列默认值。
    (可以添加一个
    BEFORE INSERT
    触发器来执行更复杂的魔法 - 如果你知道自己在做什么。)

  2. 删除

    NOT NULL
    约束。

  3. col3
    中的
    INSERT
    提供非空值。您可以在
    UPDATE
    中应用或删除相同的内容。喜欢:

    INSERT INTO player(id, col1, col2, col3)  -- !
    VALUES (val_id, val1, val2, val3)         -- !
    ON     CONFLICT (id) DO UPDATE
    SET    col1 = excluded.col1
         , col2 = excluded.col2
    --   , col3 = excluded.col3               -- optional
    ;
    

(这同样适用于您添加的表定义中的

col4
。)

© www.soinside.com 2019 - 2024. All rights reserved.