Is there a way to change existing primary key type from int to serial without dropping the table? I already have a lot of data in the table and I don't want to delete it.
Asked
Active
Viewed 4.7k times
2 Answers
106
Converting an int to a serial more or less only means adding a sequence default to the value, so to make it a serial;
Pick a starting value for the serial, greater than any existing value in the table
SELECT MAX(id)+1 FROM mytable
Create a sequence for the serial (tablename_columnname_seq is a good name)
CREATE SEQUENCE test_id_seq MINVALUE 3
(assuming you want to start at 3)Alter the default of the column to use the sequence
ALTER TABLE test ALTER id SET DEFAULT nextval('test_id_seq')
Alter the sequence to be owned by the table/column;
ALTER SEQUENCE test_id_seq OWNED BY test.id
And as always, make a habit of running a full backup before running altering SQL queries from random people on the Internet ;-)

Joachim Isaksson
- 176,943
- 25
- 281
- 294
-
But how can we used this incremented value in different table as foreign key .It is giving null value in other to which it is linked. – Anupam Haldkar May 23 '20 at 18:26
-
Can anyone explain why the permission ownership `ALTER SEQUENCE test_id_seq OWNED BY test.id` query is important? I have mismatched schemas so cant run this. – Connor Willoughby Feb 05 '21 at 17:44
-
2@ConnorWilloughby From [the documentation](https://www.postgresql.org/docs/12/datatype-numeric.html#DATATYPE-SERIAL) (for PostgreSQL version 12) describing the practical effects of using SERIAL type for a table column, 'the sequence is marked as “owned by” the column, so that it will be dropped if the column or table is dropped.' That is, a DROP of the column or table will now cascade, getting rid of the sequence as well. Convenience! – Thomas Capote Mar 15 '21 at 17:52
-3
-- temp schema for testing
-- ----------------------------
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE bagger
( id INTEGER NOT NULL PRIMARY KEY
, tralala varchar
);
INSERT INTO bagger(id,tralala)
SELECT gs, 'zzz_' || gs::text
FROM generate_series(1,100) gs
;
DELETE FROM bagger WHERE random() <0.9;
-- SELECT * FROM bagger;
-- CREATE A sequence and tie it to bagger.id
-- -------------------------------------------
CREATE SEQUENCE bagger_id_seq;
ALTER TABLE bagger
ALTER COLUMN id SET NOT NULL
, ALTER COLUMN id SET DEFAULT nextval('player_id_seq')
;
ALTER SEQUENCE bagger_id_seq
OWNED BY bagger.id
;
SELECT setval('bagger_id_seq', MAX(ba.id))
FROM bagger ba
;
-- Check the result
-- ------------------
SELECT * FROM bagger;
\d bagger
\d bagger_id_seq

wildplasser
- 43,142
- 8
- 66
- 109
-
What does this do? can you explain why it works or maybe other possible solutions? – Minijack Sep 24 '19 at 10:42
-
1Well:it createsa table(which the OP did not do),populates it with random values(which the OP did not do), adds a seria l*oldstyle* (which the OP intended) and makes it a primary key (which the OP intended) – wildplasser Sep 24 '19 at 20:40