How to UPDATE or INSERT in PostgreSQL
Sep 19
I want to UPDATE or INSERT a column in PostgreSQL instead of doing INSERT or UPDATE using INSERT ... ON CONFLICT ... because there will be more updates than more inserts and also I have an auto incrementing id column that's defined using SERIAL so it increments the id column everytime it tries to INSERT or UPDATE and that's not what I want, I want the id column to increase only if it's an INSERT so that all ids would be in an order instead
The table is created like this
CREATE TABLE IF NOT EXISTS table_name (
id SERIAL PRIMARY KEY,
user_id varchar(30) NOT NULL,
item_name varchar(50) NOT NULL,
code_uses bigint NOT NULL,
UNIQUE(user_id, item_name)
)
And the query I used was
INSERT INTO table_name
VALUES (DEFAULT, 'some_random_id', 'some_random_name', 1)
ON CONFLICT (user_id, item_name)
DO UPDATE SET code_uses = table_name.code_uses + 1;
Thanks :)
1 answer
Accepted answer · original discussion
Sep 19
Upserts in PostgreSQL do exactly what you described.
Consider this table and records
CREATE TABLE t (id SERIAL PRIMARY KEY, txt TEXT);
INSERT INTO t (txt) VALUES ('foo'),('bar');
SELECT * FROM t ORDER BY id;
id | txt
----+-----
1 | foo
2 | bar
(2 Zeilen)
Using upserts the id will only increment if a new record is inserted
INSERT INTO t VALUES (1,'foo updated'),(3,'new record')
ON CONFLICT (id) DO UPDATE SET txt = EXCLUDED.txt;
SELECT * FROM t ORDER BY id;
id | txt
----+-------------
1 | foo updated
2 | bar
3 | new record
(3 Zeilen)
EDIT (see coments): this is the expected behaviour of a serial column, since they're nothing but a fancy way to use sequences. Long story short: using upserts the gaps will be inevitable. If you're worried the value might become too big, use bigserial instead and let PostgreSQL do its job.
Related thread: serial in postgres is being increased even though I added on conflict do nothing
3 question comments
Use comments to ask for clarification. Post a solution as an answer.
Sep 19
insert ... on conflict.. isSep 21