Safely rename tables using serial primary key columns

serial is not an actual data type. The manual states:

The data types smallserial, serial and bigserial are not true types,
but merely a notational convenience for creating unique identifier columns

The pseudo data type is resolved doing all of this:

  • create a sequence named tablename_colname_seq

  • create the column with type integer (or int2 / int8 respectively for smallserial / bigserial)

  • make the column NOT NULL DEFAULT nextval('tablename_colname_seq')

  • make the column own the sequence, so that it gets dropped with it automatically

The system does not know whether you did all this by hand or by way of the pseudo data type serial. pgAdmin checks on the listed features and if all are met, the reverse engineered DDL script is simplified with the matching serial type. If one of the features is not met, this simplification does not take place. That is something pgAdmin does. For the underlying catalog tables it’s all the same. There is no serial type as such.

There is no way to automatically rename owned sequences. You can run:

ALTER SEQUENCE ... RENAME TO ...

like you did. The system itself doesn’t care about the name. The column DEFAULT stores an OID ('foo_pkey_seq'::regclass), you can change the name of the sequence without breaking that – the OID stays the same. The same goes for foreign keys and similar references inside the database.

The implicit index for the primary key is bound to the name of the PK constraint, which will not change if you change the name of the table. In Postgres 9.2 or later you can use

ALTER TABLE ... RENAME CONSTRAINT ..

to rectify that, too.

There can also be indexes named in reference to the table name. Similar procedure:

ALTER INDEX .. RENAME TO  ..

You can have all kinds of informal references to the table name. The system cannot forcibly rename objects that can be named anything you like. And it doesn’t care.

Of course you don’t want to invalidate SQL code that references those names. Obviously, you don’t want to change names while application logic references them. Normally this wouldn’t be a problem for names of indexes, sequences or constraints, since those are not normally referenced by name.

Postgres also acquires a lock on objects before renaming them. So if there are concurrent transaction open that have any kind of lock on objects in question, your RENAME operation is stalled until those transactions commit or roll back.

System catalogs and OIDs

The database schema is stored in tables of the system catalog in the system schema pg_catalog. All details in the manual here. If you don’t know exactly what you are doing, you shouldn’t be messing with those tables at all. One false move and you can break your database. Use the DDL commands Postgres provides.

For some of the most important tables Postgres provides object identifier types and type casts to get the name for the OID and vice versa quickly. Like:

SELECT 'foo_pkey_seq'::regclass

If the schema name is in the search_path and the table name is unique, that gives you the same as:

SELECT oid FROM pg_class WHERE relname="foo_pkey_seq";

The primary key of most catalog tables is oid and internally, most references use OIDs.

Leave a Comment