This question is asked about once a week on SO, and the answers are almost always wrong.
Here is the correct one.
insert customer (email, count) select 'foo@example.com', 0 where not exists ( select 1 from customer where email = 'foo@example.com' ) update customer set count = count + 1 where email = 'foo@example.com'
If you like, you can insert counter 1 and skip update , if the inserted row, but expressed in your DBMS, returns 1.
The above syntax is completely standard and makes no assumptions about locking mechanisms or isolation levels. If this does not work, your DBMS is broken.
Many people mistakenly believe that select fulfills the "first" and thus introduces a race condition. No: select is part of insert . The insert is atomic. No race.
James K. Lowden
source share