Question

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.

Était-ce utile?

La solution

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

A very simple SQLfiddle demo.

And as always, make a habit of running a full backup before running altering SQL queries from random people on the Internet ;-)

Autres conseils

-- 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top