Follow the below script to create two tables source_t and dest_t.
drop table if exists source_t;
create table source_t as
(select 1 id, 'dummy1' varcol union
select 3,'dummy3');
drop table if exists dest_t;
create table dest_t as
(select 1 id, 'mmy' varcol
union select 2,'dummy2');
ALTER TABLE dest_t
ALTER id SET NOT NULL,
ALTER id ADD GENERATED ALWAYS AS identity;
ALTER TABLE dest_t ADD CONSTRAINT UNQ_CON_dest_t unique (id);
Now the content of two tables:
source_t:
dest_t:
1st case is when I want to update a record using upsert: Now my upsert statement:
insert into dest_t
select * from source_t
on conflict on constraint unq_con_dest_t
do update set (varcol)=( select excluded.varcol);
The expectation is to just update varcol column for id = 1 in the dest_t table.
The error I am getting :
ERROR: cannot insert into column "id"
Detail: Column "id" is an identity column defined as GENERATED ALWAYS.
First question: Why am I getting insert error while the select query is returning only data which is the "updateable" candidate.
OK. Now I change my upsert as below to see if it gets fixed:
insert into dest_t OVERRIDING SYSTEM VALUE
select * from source_t
on conflict on constraint unq_con_dest_t
do update set (varcol)=( select excluded.varcol);
And even though this is not a fix, let's say I was able to proceed with the expected update.
2nd case:
let's insert a record in source_t as below, since this does not exist in dest_t this can be a "insert" candidate for dest_t :
insert into source_t values(null,'dummy0');
Running same upsert statement:
insert into dest_t OVERRIDING SYSTEM VALUE
select * from source_t
on conflict on constraint unq_con_dest_t
do update set (varcol)=( select excluded.varcol);
Now I get the below error:
ERROR: null value in column "id" violates not-null constraint
Yes, I understand it cannot insert null to not null column. I get the same error with or without using the "overriding" clause.
Second question: How do I make sure the upsert query automatically increments identity column when it is inserting and while updating it uses the existing value returned in select query of upsert. And identity column is the unique key.
Or is it not possible to use "UPSERT" when the unique key of the destination table is the "identity" column.?
set (varcol)=( select excluded.varcol);
can be simplified toset varcol = excluded.varcol