I have two tables: demo at db<>fiddle
- Table
keywordshas two columnsidandv(which hold the keyword's value)create table keywords( id int generated always as identity primary key ,v text unique); - Table
mainhas, among others, two columns that are each a foreign key into thekeywordstable'sid, namedkey1_idandkey2_idcreate table main( id int generated always as identity primary key ,key1_id int references keywords(id) ,key2_id int references keywords(id));
Now, I want to insert pairs of keywords (key1 and key2 as $1 and $2) into the main table, like this:
WITH key1 AS (INSERT INTO keywords (v)
VALUES ($1)
ON CONFLICT (v) DO UPDATE
SET v = EXCLUDED.v
RETURNING id),
key2 AS (INSERT INTO keywords (v)
VALUES ($2)
ON CONFLICT (v) DO UPDATE
SET v = EXCLUDED.v
RETURNING id)
INSERT INTO main (key1_id, key2_id)
SELECT key1.id, key2.id
FROM key1, key2
RETURNING id
Basically, the two keys often have recurring values, so I use the keywords table to keep a unique set of them (mostly for storage optimization, as I have millions of rows with them).
But if $1 and $2 have identical values, I get this error, whereas there's no issue if they're different:
pg_query_params(): Query failed: ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time
HINT: Ensure that no rows proposed for insertion within the same command have duplicate constrained values.
The goal is that both key1_id and key2_id point to the correct row in keywords based on the values passed as $1 and $2, even if they're both the same.
How do I modify the SQL statement (ideally, it should remain a single one) so that I can insert these keys without getting the error?
I am using Postgresql 16.9.