¿Cómo modifico la posición de una columna en una tabla de base de datos PostgreSQL?

Respuestas:

106

" Alterar la posición de la columna " en el Wiki de PostgreSQL dice:

PostgreSQL actualmente define el orden de las attnumcolumnas según la columna de la pg_attributetabla. La única forma de cambiar el orden de las columnas es recreando la tabla o agregando columnas y rotando datos hasta llegar al diseño deseado.

Eso es bastante débil, pero en su defensa, en SQL estándar, tampoco hay una solución para reposicionar una columna. Las marcas de bases de datos que admiten el cambio de la posición ordinal de una columna están definiendo una extensión de la sintaxis SQL.

Se me ocurre otra idea: puedes definir un VIEWque especifique el orden de las columnas como más te guste, sin cambiar la posición física de la columna en la tabla base.

Bill Karwin
fuente
3
@Dana: Creo que eso es lo que significa "recrear la mesa" en el artículo de la wiki.
Bill Karwin
2
'dump the database' :: excelente manera de dañar los datos. y por lo tanto, el efecto de "limpiar la base de datos masiva".
Kent Fredric
31
@Kent: Dudoso, los desarrolladores de Postgres recorren un largo camino para garantizar la coherencia de los datos y eso ciertamente se aplicaría a pg_dump. Después de todo, ¿cuál es el punto de hacer copias de seguridad de la base de datos si la restauración no funciona?
Dana the Sane
@Dana, sí, pero está agregando 1) un gran proceso para volcar, y luego lo suelta, y luego tiene una gran carga que consume mucho tiempo. Si tiene una base de datos seriamente masiva, que suele ser el caso con 37 columnas, tendrá riesgos de obstrucción de E / S del disco.
Kent Fredric
@DanatheSane estos son comentarios súper antiguos , pero lo que Bill estaba diciendo es esencialmente lo mismo, en lugar de hacer un volcado completo de la base de datos, simplemente vuelca la tabla (y las dependencias), mata el original y luego vuelve a crear. No es necesario desconectar toda la base de datos ni perder tiempo recreando algo que no se ve afectado. Por otro lado, si hay muchas dependencias, he descubierto que hacer un volcado completo (como sugirió) es mucho más fácil.
vol7ron
36

En PostgreSQL, al agregar un campo, se agregaría al final de la tabla. Si necesitamos insertar en una posición particular, entonces

alter table tablename rename to oldtable;
create table tablename (column defs go here);
insert into tablename (col1, col2, col3) select col1, col2, col3 from oldtable;
Todos ganan
fuente
3
¡Vaya, esto es genial, estoy seguro de que esta debería ser la respuesta aceptada!
Tommaso Thea Cioni
Sí, es realmente útil, ¡muchas gracias!
Acuña
También puede copiar la tabla actual a una nueva tabla antigua como esta: CREATE TABLE tabla antigua AS SELECT * FROM tablename;
Ryan
29

Esta publicación es antigua y probablemente esté resuelta, pero tuve el mismo problema. Lo resolví creando una vista de la tabla original especificando el nuevo orden de columna.

Desde aquí, podría usar la vista o crear una nueva tabla desde la vista.

    CREAR VER original_tab_vw COMO
    SELECCIONE a.col1, a.col3, a.col4, a.col2
    FROM original_tab a
    DONDE a.col1 NO ES NULO - o lo que sea
    SELECT * INTO new_table FROM original_tab_vw

Cambie el nombre o elimine la tabla original y establezca el nombre de la tabla nueva en la tabla anterior.

Conocido
fuente
2
Esta parece una solución bastante razonable. Es una lástima que no haya ninguna herramienta GUI para automatizar este procedimiento.
Preguntas de Quolonel
4
buena solución, pero solo se copian los tipos de datos (sin clave principal, etc.)
Regisz
1
Alternativamente, simplemente use la vista con las columnas reordenadas tal como están. Debe haber una degradación mínima del rendimiento.
pscl
1
Esta es la mejor solución.
Nikolay Shindarov
23

Una, aunque una opción torpe para reorganizar las columnas cuando el orden de las columnas debe cambiarse absolutamente y las claves externas están en uso, es primero volcar toda la base de datos con datos y luego volcar solo el esquema ( pg_dump -s databasename > databasename_schema.sql). A continuación, edite el archivo de esquema para reorganizar las columnas como desee, luego vuelva a crear la base de datos a partir del esquema y, finalmente, restaure los datos en la base de datos recién creada.

Ville
fuente
1
¿Por qué un voto negativo? Como señala la respuesta aceptada, citando el Wiki de PostgreSQL: »La única forma de cambiar el orden de las columnas es recreando la tabla o agregando columnas y rotando los datos hasta llegar al diseño deseado.» Esta solución no es óptima (ninguna de estas respuestas está en ausencia de una operación incorporada para realizar la tarea), pero proporciona una forma de reorganizar las columnas en una tabla.
Ville
1
Repito, no hay buenas formas de hacer esto, y lo que describo anteriormente es una forma válida de reorganizar las columnas si es absolutamente necesario reorganizarlas. Si rechaza mi respuesta, comente por qué cree que es una solución inaceptable.
Ville
3
De hecho, esta es una muy buena solución cuando la tabla es una clave externa en otras tablas. Todas las demás soluciones no funcionan en este escenario. Finalmente, use pg_dump --column-inserts -s databasename> databasename_schema.sql
Alejandro Salamanca Mazuelo
9

No creo que pueda en este momento: vea este artículo en la wiki de Postgresql .

Las tres soluciones alternativas de este artículo son:

  1. Recrear la mesa
  2. Agregar columnas y mover datos
  3. Oculta las diferencias con una vista.
Mike Woodhouse
fuente
5

Abra la tabla en PGAdmin y en el panel SQL en la parte inferior copie la declaración SQL Create Table. Luego abra la Herramienta de consulta y péguela. Si la tabla tiene datos, cambie el nombre de la tabla a 'new_name', de lo contrario, elimine el comentario "-" en la línea Drop Table. Edite la secuencia de columnas según sea necesario. Tenga en cuenta la coma faltante / superflua en la última columna en caso de que la haya movido. Ejecute el nuevo comando SQL Create Table. Refresca y ... voilà.

Para tablas vacías en la etapa de diseño, este método es bastante práctico.

En caso de que la tabla tenga datos, también debemos reorganizar la secuencia de columnas de los datos. Esto es fácil: use INSERTpara importar la tabla anterior a su nueva versión con:

INSERT INTO new ( c2, c3, c1 ) SELECT * from old;

... donde c2, c3, c1son las columnas c1, c2, c3de la mesa de edad en sus nuevas posiciones. Tenga en cuenta que en este caso debe utilizar un nombre "nuevo" para la tabla "antigua" editada o perderá sus datos . En caso de que los nombres de las columnas sean muchos, largos y / o complejos, use el mismo método que el anterior para copiar la nueva estructura de la tabla en un editor de texto y cree la nueva lista de columnas allí antes de copiarla en la INSERTdeclaración.

Después de comprobar que todo está bien, DROPutilice la tabla antigua y cambie el nombre 'nuevo' a 'antiguo' ALTER TABLE new RENAME TO old;y ya está.

Marco Polo
fuente
1

Estaba trabajando en reordenar muchas tablas y no quería tener que escribir las mismas consultas una y otra vez, así que hice un script para hacerlo todo por mí. Esencialmente,

  1. Obtiene el SQL de creación de tablas de pg_dump
  2. Obtiene todas las columnas disponibles del volcado
  3. Coloca las columnas en el orden deseado
  4. Modifica la pg_dumpconsulta original para crear una tabla reordenada con datos.
  5. Gotas de mesa vieja
  6. Cambia el nombre de la tabla nueva para que coincida con la tabla anterior

Se puede utilizar ejecutando el siguiente comando simple:

./reorder.py -n schema -d database table \
    first_col second_col ... penultimate_col ultimate_col --migrate

Imprime el sql para que pueda verificarlo y probarlo, esa fue una gran razón en la que lo basé pg_dump. Puedes encontrar el repositorio de github aquí .

GammaGames
fuente
0

Yo uso Django y requiere una columna de identificación en cada tabla si no quieres tener un dolor de cabeza. Desafortunadamente, fui descuidado y mi tabla bp.geo_location_vague no contenía este campo. Puse mis iniciales en un pequeño truco. Paso 1:

CREATE VIEW bp.geo_location_vague_vw AS
    SELECT 
        a.id, -- I change order of id column here. 
        a.in_date,
        etc
    FROM bp.geo_location_vague a

Paso 2: (sin crear tabla, ¡la tabla se creará automáticamente!)

SELECT * into bp.geo_location_vague_cp2 FROM bp.geo_location_vague_vw

Paso 3:

CREATE SEQUENCE bp.tbl_tbl_id_seq;
ALTER TABLE bp.geo_location_vague_cp2 ALTER COLUMN id SET DEFAULT nextval('tbl_tbl_id_seq');
ALTER SEQUENCE bp.tbl_tbl_id_seq OWNED BY bp.geo_location_vague_cp2.id;
SELECT setval('tbl_tbl_id_seq', COALESCE(max(id), 0)) FROM bp.geo_location_vague_cp2;

Porque necesito tener un pseudotipo de serie grande en la mesa. Después de SELECCIONAR * en pg, se creará un tipo bigint insertado en bigserial.

Paso 4: Ahora podemos eliminar la vista, eliminar la tabla de origen y cambiar el nombre de la nueva tabla con el nombre anterior. El truco se terminó con éxito.

Orlov Const
fuente