Como cambiar el orden de las columnas de una tabla en PostgreSQL
0. Como base, tenemos una tabla de ejemplo
# CREATE TABLE test (a int, b int, c int); # INSERT INTO test VALUES (1,2,3); # SELECT * FROM test; a | b | c ---+---+--- 1 | 2 | 3 (1 row)
Queremos que la columna b quede antes que la columna a.
1. Nos logeamos en la base de datos con el usuario postgres para poder editar las tablas de sistema.
2. Buscamos el valor attrelid de la tabla que queremos modificar en la tabla pg_class:
# SELECT relname, relfilenode FROM pg_class WHERE relname='test'; relname | relfilenode ---------+------------- test_t | 27666 (1 row)
Luego consultamos la tabla pg_attribute para encontrar la tabla, las columnas y la posición de las columnas, con el valor que nos retornó la búsqueda anterior.
# SELECT attrelid, attname, attnum FROM pg_attribute WHERE attrelid=27666; attrelid | attname | attnum ----------+----------+-------- 27666 | tableoid | -7 27666 | cmax | -6 27666 | xmax | -5 27666 | cmin | -4 27666 | xmin | -3 27666 | ctid | -1 27666 | a | 1 27666 | b | 2 27666 | c | 3 (9 rows)
Aquí podemos tener un problema y es que puede que el primer comando no nos retorne nada o nos retorne un valor diferente al que buscamos. De no encontrar la tabla con el primer comando, podemos buscar directamente en la tabla pg_attribute por el nombre de nuestra columna, si este no es común a otras tablas y verificando cuidadosamente que la tabla que buscamos es la que nos interesa.
# SELECT attrelid, attname, attnum FROM pg_attribute WHERE attname=a; attrelid | attname | attnum ----------+----------+-------- 27666 | a | 1 (1 rows)
3. Modificamos el valor de attnum de las columnas.
Ya que attnum es una columna de valores únicos (en realidad yo creo que se trata de un constraint compuesto), tenemos que usar un valor temporal mientras modificamos el valor.
# UPDATE pg_attribute SET attnum=4 WHERE attname='a' AND attrelid=27666; UPDATE 1 # UPDATE pg_attribute SET attnum=1 WHERE attname='b' AND attrelid=27666; UPDATE 1 # UPDATE pg_attribute SET attnum=2 WHERE attname='a' AND attrelid=27666; UPDATE 1
Luego consultamos la tabla para saber que hicimos las cosas bien
# SELECT * FROM test; b | a | c ---+---+--- 1 | 2 | 3 (1 row)
No sobra recordar que estamos modificando las tablas de sistema, entonces debemos ser muy cuidadosos.
Esto funciona muy bien para PostgreSQL 8.3 (lo tuve que utilizar una sola vez). No sé si para otras versiones, sobre todo las anteriores, el truco también funcione.
Nota.- El contenido de la página original esta bajo una licencia Creative Commons Atribución, Compartir Igual y este artículo se ofrece bajo la misma licencia.

Comment from Jaime Casanova
Time 2010.01.13 at 00:49
Esto no funciona, si los tipos de datos son distintos PostgreSQL fallara feamente, aun en este caso en el que los tipos de datos son identicos lo que se hizo fue cambiar a la columna a por el nombre b y viceversa… por eso en el resultado final b tiene 1 y a tiene 2