ID | info
---------
1 | xxx
2 | xxx
4 | xxx
I have a setup similar to this in PostgreSQL. (I'm using a mac running Mojave if that makes a difference).
I have a few more columns but the issue is the ID column. This was set to be sequential, so using Express I insert into the DB.
Problem is, it increments the ID on every insert even failing inserts. info is defined unique, so trying to insert an existing info returns an error. But ID is still incremented.
For example, if I insert 2 rows, I have id 1 & id 2. Then another one that fails with a unique violation. The the next successful insert gets id = 4, skipping id = 3.
Can I set up Postgres so it doesn't increment on failed inserts?
serial columns, or IDENTITY in Postgres 10 or later, draw numbers from a SEQUENCE and gaps are to be expected. Their job is to make concurrent write access possible with unique numbers - not necessarily gap-less numbers.
If you don't actually have concurrent write access, there are simple ways to achieve (mostly) gap-less numbers. Like:
INSERT INTO tbl (info)
SELECT 'xxx'
WHERE NOT EXISTS (SELECT FROM tbl WHERE info = 'xxx');
That doesn't burn a serial ID from the SEQUENCE because a duplicate insert is skipped. (The INSERT might still fail for any other reason - and burn a serial number. You could reset the SEQUENCE in such a case:
While inserting multiple rows in a single statement, you also have to rule out duplicates within the inserted set. Example code:
But if you do have concurrent writes, none of the above works reliably, on principle. You better learn to accept gaps in the IDs. You can always have a query with row_number() OVER (ORDER BY id) to generate gap-less numbers after the fact. However, the numbers are still arbitrary to a degree. Smaller numbers were not necessarily committed earlier. There are exceptions under concurrent write load. Related:
Or consider a UUID instead (dat type uuid) and avoid the inherent problem of duplicates with random values in a huge key space. Not at all serial, though:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With