Pregunta

¿Es posible cambiar el orden natural de las columnas en Postgres 8.1?

Sé que no deberías confiar en el orden de las columnas, no es básico a lo que estoy haciendo: solo lo necesito para que algunas cosas generadas automáticamente salgan de una manera más agradable, de modo que el orden de los campos coincida desde pgadmin hasta el back-end y el front-end.

¿Fue útil?

Solución

De hecho, puedes simplemente cambiar el orden de las columnas, pero no lo recomendaría y debes tener mucho cuidado si decides hacerlo.

p.ej.

# 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)

Ahora, para lo complicado, debe conectarse a su base de datos utilizando el usuario de postgres para poder modificar las tablas del sistema.

# SELECT relname, relfilenode FROM pg_class WHERE relname='test';
 relname | relfilenode 
---------+-------------
 test_t  |       27666
(1 row)

# 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 | b        |      1
    27666 | a        |      2
    27666 | c        |      3
(9 rows)

attnum es una columna única, por lo que necesita usar un valor temporal cuando modifica los números de columna como tal:

# 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

# SELECT * FROM test;
 b | a | c 
---+---+---
 1 | 2 | 3
(1 row)

Nuevamente, debido a que esto es jugar con las tablas del sistema de bases de datos, tenga mucho cuidado si cree que realmente necesita hacerlo.

Esto funciona a partir de Postgres 8.3; con versiones anteriores, su kilometraje puede variar.

Otros consejos

Si su base de datos no es muy grande y puede permitirse un tiempo de inactividad, entonces puede:

  1. Deshabilitar el acceso de escritura a la base de datos.
    Esto es esencial ya que de lo contrario se perderán todos los cambios después de comenzar el siguiente punto.
  2. pg_dump --create --column-inserts databasename > databasename.pgdump.sql
  3. Editar apropiado CREATE TABLE declaración en nombre de base de datos.pgdump.sql
    Si el archivo es demasiado grande para su editor, simplemente divídalo usando split Comando, edite y luego vuelva a ensamblar usando cat
  4. drop database databasename
    Tienes una copia de seguridad reciente, por si acaso, ¿verdad?
  5. psql --single-transaction -f databasename.pgdump.sql
    Si no usas --single-transaction será muy lento

Si utiliza los llamados objetos grandes, asegúrese de que estén incluidos en el volcado.No estoy seguro si están por defecto en 8.1.

Hice esa pregunta en pgsql-admin en 2007.El propio Tom Lane declaró prácticamente inviable cambiar el orden en los catálogos.

Aclaración:para los usuarios, con las herramientas actuales.No significa que no se pueda implementar.En mi opinión, debería serlo.
Sigue siendo cierto para Postgres 11.

Como mencionaron las otras respuestas, no puede cambiar el orden de las columnas, eso depende de postgres.Puedes (¡y debes!) resolver tu problema con una vista.A los efectos de su consulta de informes, se verá como una tabla.Algo como:

create view my_view as
  select * from my_table
  order by some_col;

Especificar el orden de las columnas en la consulta es la única forma confiable (y sensata).Dicho esto, generalmente puede obtener un orden diferente modificando la tabla como se muestra en el siguiente ejemplo, ya que las columnas generalmente (no se garantiza que lo sean) se devuelven en el orden en que se agregaron a la tabla.

postgres=# create table a(a int, b int, c int);
CREATE TABLE
postgres=# insert into a values (1,2,3);
INSERT 0 1
postgres=# select * from a;
 a | b | c
---+---+---
 1 | 2 | 3
(1 row)

postgres=# alter table a add column a2 int;
ALTER TABLE
postgres=# select * from a;
 a | b | c | a2
---+---+---+----
 1 | 2 | 3 |
(1 row)

postgres=# update a set a2 = a;
UPDATE 1
postgres=# alter table a drop column a;
ALTER TABLE
postgres=# alter table a rename column a2 to a;
ALTER TABLE
postgres=# select * from a;
 b | c | a
---+---+---
 2 | 3 | 1
(1 row)

postgres=#

Lamentablemente no, no lo es.El orden de las columnas depende completamente de Postgres.

Puede obtener el orden de columnas que desea creando una nueva tabla y seleccionando las columnas de la tabla anterior en el orden en que desea que se presenten:

CREATE TABLE test_new AS SELECT b, c, a FROM test;
SELECT * from test_new;
 b | c | a 
---+---+---
 2 | 3 | 1
(1 row)

Tenga en cuenta que esto copia solo datos, no modificadores, restricciones, índices, etc.

Una vez que la nueva tabla se modifique de la forma deseada, suelte la original y modifique el nombre de la nueva:

BEGIN;
DROP TABLE test;
ALTER TABLE test_new RENAME TO test;
COMMIT;

Yo quiero lo mismo.Sí, es imprescindible pedirlo ahora, pero me molesta :)

Lo que estoy haciendo para resolverlo es lo siguiente.

Este método garantizará que CONSERVE todos los datos existentes,

  1. Cree una nueva versión de la tabla usando el orden que quiero, usando un nombre temporal.
  2. Inserte todos los datos en esa nueva tabla de la existente.
  3. Deja la vieja mesa.
  4. Cambie el nombre de la nueva tabla al "nombre propio" de "nombre temporal".
  5. Vuelva a agregar los índices que tenía anteriormente.
  6. Restablecer la secuencia de ID para incrementos de clave principal.

Orden actual de la mesa:

id, name, email

1.Cree una nueva versión de la tabla usando el orden que quiero, usando un nombre temporal.

En este ejemplo, quiero email estar antes name.

CREATE TABLE mytable_tmp
(
  id SERIAL PRIMARY KEY,
  email text,
  name text
);

2.Inserte todos los datos en esa nueva tabla de la existente.

INSERT INTO mytable_tmp   --- << new tmp table
(
  id
, email
, name
)
SELECT
  id
, email
, name
FROM mytable;  --- << this is the existing table

3.Deja la vieja mesa.

DROP TABLE mytable;

4.Cambie el nombre de la nueva tabla al "nombre propio" de "nombre temporal".

ALTER TABLE mytable_tmp RENAME TO mytable;

5.Vuelva a agregar los índices que tenía anteriormente.

CREATE INDEX ...

6.Restablecer la secuencia de ID para incrementos de clave principal.

SELECT setval('public.mytable_id_seq', max(id)) FROM mytable;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top