我有一个表player
,其中包含以下命令。我只更改了列名和顺序:
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”的列“col 3”中的空值违反了not-null约束
当我给col3
一个默认值时,没有错误发生,所有的值都是它们应该的。
我检查了Postgres文档,但找不到查询的错误。可能是什么问题?
1条答案
按热度按时间mepcadol1#
TL;DR
如果
col3
定义为NOT NULL
而没有默认值,则INSERT
* 必须 * 为其提供非空值。深入了解
首先检查
NOT NULL
约束。手册:当一个表有多个
CHECK
约束时,将按名称的字母顺序对每行进行测试,在检查NOT NULL
约束之后。大胆强调我的。
你可能会尝试将
NOT NULL
替换为普通的CHECK
约束。非空约束总是写为列约束。非空约束在功能上等效于创建检查约束
CHECK
(column_name IS NOT NULL
),但在PostgreSQL中创建显式非空约束更有效。缺点是您不能为以这种方式创建的非空约束提供给予显式名称。但是没有用。任何一个约束都是立即检查的,不能推迟。手册:
NOT NULL
和CHECK
约束总是在插入或修改行时立即检查(而不是在语句的末尾)。大胆强调我的。
这是核心问题。
执行以下操作之一来解决:
1.为
col3
定义非空列默认值。(如果您知道自己在做什么,可以添加一个
BEFORE INSERT
触发器来执行更复杂的魔术。1.删除
NOT NULL
约束。1.在
INSERT
中为col3
提供一个非空值。您可以在UPDATE
中应用或删除相同的值。例如:字符串
(The这同样适用于您添加的表定义中的
col4
。