我有一张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
);

下面是我try 运行的查询:

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"中的空值违反非空约束

当我给col3设置一个缺省值时,没有出现错误,所有的值都是应该的.但我不需要缺省值.

我判断了Postgres文档,但找不到查询的错误.有什么问题吗?

推荐答案

TL;DR

如果col3被定义为NOT NULL而没有默认值,则INSERT must为其提供非空值.

深入

首先判断NOT NULL个约束.The manual:

当一个表有多个CHECK约束时, 每行按名称的字母顺序排列,after checking 101 constraints.

Bold emphasis mine.
You might try to replace NOT NULL with a plain CHECK constraint. The manual:

非空约束始终写入为列约束.一个 非空约束在功能上等同于创建判断 约束CHECK(column_name IS NOT NULL),但在PostgreSQL中 创建显式的非空约束更有效.这个 缺点是您不能为非空值指定显式名称 以这种方式创建的约束.

而是to no avail.这两个约束都是立即判断的,不能推迟.The manual:

100 and 101 constraints are always checked immediately何时 插入或修改行(不在语句的末尾).

Bold emphasis mine.
This is the core issue.

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

  1. Define a non-null column default for col3.
    (Possibly add a BEFORE INSERT trigger to do more sophisticated magic - if you know what you are doing.)

  2. 取消NOT NULL限制.

  3. INSERT中的col3提供一个非空值.您可以在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.)

Sql相关问答推荐

Microsoft Access UNION将长文本字段限制为255个字符

如何在一个范围内进行分组.""范围值在范围表中定义

基于时间的SQL聚合

如何更改函数返回的列名?

如何在case语句中使用条件来计算成对变量

如何转换和汇总行数

如何在Snowflake SQL存储过程中传递LIMIT和OFFSET的参数?

基于多个字段删除Access中的重复记录,同时保留最低优先级

在Oracle中,如何删除具有特定值的行,仅当它是重复的行?

PostgreSQL基于2个COLS的任意组合 Select 唯一行

正在try 从SQL获取最新的ID和一个唯一名称

冲突查询的UPDATE时违反非空约束

如何在SQL中从多个查询进行分组

根据时间值提取记录

如何修复初学者 SQL INNER JOIN 查询错误

如何将 START 和 END 日期之间的日期差异作为 SQL 中的单独列获取

在 SQL Server 中查找重复项

PostgreSQL中如何提取以特定字符开头的字符串中的所有单词?

多行状态下的分组查询判断状态

BigQuery 错误:SELECT 列表表达式引用 esthetician.LICENSE_TYPE,它既未在 [49:8] 分组也未聚合