我有一个表
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 文档,但找不到查询有什么问题。可能是什么问题?
如果
col3
定义为 NOT NULL
而没有默认值,则 INSERT
必须 为其提供非空值。
NOT NULL
约束。 说明书:
当一个表有多个
约束时,将对它们进行测试 每行按名称字母顺序排列,检查后CHECK
限制。NOT NULL
我的粗体强调。
您可能尝试用普通的
NOT NULL
约束替换CHECK
。 说明书:
非空约束总是写为列约束。 A 非空约束在功能上等同于创建检查 约束
(CHECK
),但在 PostgreSQL 中 创建显式非空约束更加有效。这 缺点是你不能给 not-null 指定明确的名称 以这种方式创建的约束。column_name IS NOT NULL
但是无济于事。任一约束都会立即检查,并且不能推迟。 说明书:
和NOT NULL
约束总是立即检查 插入或修改一行(不在语句末尾)。CHECK
我的粗体强调。
这是核心问题。
执行以下操作之一来解决:
为
col3
定义非空列默认值。BEFORE INSERT
触发器来执行更复杂的魔法 - 如果你知道自己在做什么。)
删除
NOT NULL
约束。
为
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
。)