I have a table player with the following DDL. I only changed the column names and the order:
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
);
Here's the query I tried to run:
insert into player(id, col1, col2)
values (val_id, val1, val2)
on conflict(id)
do update set col1=excluded.col1, col2=excluded.col2
(Another row with the same id exists, so UPDATE should happen.)
col3 has a NOT NULL constraint. (I verified that it has a value before the query.) Yet, when the query runs, Postgres tells me:
ERROR: ... null value in column "col3" of relation "player" violates not-null constraint
When I gave col3 a default value, no error occurred and all the values were as they should be. But I don't need a default value.
I checked the Postgres docs but cannot find what is wrong with the query. What could be the problem?
TL;DR
If
col3is definedNOT NULLwithout default, theINSERTmust provide a non-null value for it.In depth
NOT NULLconstraints are checked first. The manual:Bold emphasis mine.
You might try to replace
NOT NULLwith a plainCHECKconstraint. The manual:But to no avail. Either constraint is checked immediately, and cannot be deferred. The manual:
Bold emphasis mine.
This is the core issue.
Do one of these to resolve:
Define a non-null column default for
col3.(Possibly add a
BEFORE INSERTtrigger to do more sophisticated magic - if you know what you are doing.)Remove the
NOT NULLconstraint.Provide a non-null value for
col3in theINSERT. You can apply or drop the same in theUPDATE. Like:(The same applies to
col4in your added table definition.)