I have the following table with a combo key columns
CREATE TABLE IF NOT EXISTS MyTable
(
ColumnID1 integer NOT NULL,
ColumnID2 integer NOT NULL,
ColumnName character varying(1000),
CONSTRAINT "MyTable_pkey" PRIMARY KEY (ColumnID1, ColumnID2),
CONSTRAINT "MyTable-ColumnID1-ColumnName-Unique-Key" UNIQUE (ColumnID1, ColumnName)
)
let’s add 2 rows to the table
insert into MyTable
values
(1, 1, 'a'), (1, 2, 'b')
I can UPSERT the following values to my table using
--======= Update the 2 rows with new values (SUCCESS)
insert into MyTable (ColumnID1, ColumnID2, ColumnName)
values (1, 1, 'c'), (1, 2, 'd')
on conflict (ColumnID1, ColumnID2)
do update
set
ColumnName = EXCLUDED.ColumnName
But when I try to swap the ColumnName value for the two rows I get an error
insert into MyTable (ColumnID1, ColumnID2, ColumnName)
values (1, 1, 'd'), (1, 2, 'c')
on conflict (ColumnID1, ColumnID2)
do update
set
ColumnName = EXCLUDED.ColumnName
It complains about ColumnID1, ColumnName uniquenss
ERROR: Key (columnid1, columnname)=(1, d) already exists.duplicate key value violates unique constraint "MyTable-ColumnID1-ColumnName-Unique-Key"
ERROR: duplicate key value violates unique constraint "MyTable-ColumnID1-ColumnName-Unique-Key"
SQL state: 23505
Detail: Key (columnid1, columnname)=(1, d) already exists.
How can I change my upsert query to allow swapping values in existing rows.
I tried appending ColumnName
to the ON CONFLICT condition but that doesn’t work either
3
Answers
You can solve issue using DEFERRED UNIQUE KEY:
Test it here
The DEFERRED constraints are not checked until transaction commit.
To be able to swap values from existing rows you need to change the ON CONFLICT condition to include the ColumnName column.
The following query can help you solve this :
One approach I can think off the top of my head is you simply remove the constraint and add it back after doing your update. Possibly, like so: