I'm trying to insert a row but only if it is not already present in the table. At the moment I'm using code similar to the following:
insert into mentions (project_id, id, data_source, channel)
select 3, '123456789', 'example.com', 'twitter'
where not exists
(select 1 as "one" from mentions where (project_id = 3 and id = '123456789'))
returning reach;
But I sometimes see it fail with the following error in the logs
ERROR: duplicate key value violates unique constraint "mentions_pkey"
DETAIL: Key (project_id, id)=(3, 123456789) already exists.
and the constraint is defined as
Index "public.mentions_pkey"
┌────────────┬─────────┬────────────┐
│ Column │ Type │ Definition │
├────────────┼─────────┼────────────┤
│ project_id │ integer │ project_id │
│ id │ text │ id │
└────────────┴─────────┴────────────┘
primary key, btree, for table "public.mentions"
Since I'm only inserting when the exists clause is false, I don't understand how this can ever fail with a constraint violation.
Could it be a concurrency issue? I was under the assumption that individual statements are atomic but maybe this isn't the case?
I know that once 9.5 ships I can use ON CONFLICT DO NOTHING
, but I'm running 9.4 at the moment.