How do I alter the position of a column in a PostgreSQL database table?

This post is old and probably solved but I had the same issue. I resolved it by creating a view of the original table specifying the new column order.

From here I could either use the view or create a new table from the view.

    CREATE VIEW original_tab_vw AS
    SELECT a.col1, a.col3, a.col4, a.col2
    FROM original_tab a
    WHERE a.col1 IS NOT NULL --or whatever
    SELECT * INTO new_table FROM original_tab_vw

Rename or drop the original table and set the name of the new table to the old table.


"Alter column position" in the PostgreSQL Wiki says:

PostgreSQL currently defines column order based on the attnum column of the pg_attribute table. The only way to change column order is either by recreating the table, or by adding columns and rotating data until you reach the desired layout.

That's pretty weak, but in their defense, in standard SQL, there is no solution for repositioning a column either. Database brands that support changing the ordinal position of a column are defining an extension to SQL syntax.

One other idea occurs to me: you can define a VIEW that specifies the order of columns how you like it, without changing the physical position of the column in the base table.


One, albeit a clumsy option to rearrange the columns when the column order must absolutely be changed, and foreign keys are in use, is to first dump the entire database with data, then dump just the schema (pg_dump -s databasename > databasename_schema.sql). Next edit the schema file to rearrange the columns as you would like, then recreate the database from the schema, and finally restore the data into the newly created database.


In PostgreSQL, while adding a field it would be added at the end of the table. If we need to insert into particular position then

    alter table tablename rename to oldtable;
    create table tablename (column defs go here); ### with all the constraints
    insert into tablename (col1, col2, col3) select col1, col2, col3 from oldtable;