2009-08-07 26 views
44

¿Cómo agregar una nueva columna en una tabla después de la 2ª o 3ª columna en la tabla usando postgres?¿Cómo agregar una nueva columna en una tabla después de la 2ª o 3ª columna en la tabla usando postgres?

Mi código es como sigue

ALTER TABLE n_domains ADD COLUMN contract_nr int after owner_id 
+2

El orden de las columnas es totalmente irrelevante en las bases de datos relacionales, solo se trata de mostrarlas en una herramienta. La tabla de la base de datos no tiene ningún orden de las columnas. –

Respuesta

49

No, no hay forma directa de hacer eso. Y hay una razón para ello: cada consulta debería enumerar todos los campos que necesita en cualquier orden (y formato, etc.) que los necesite, haciendo que el orden de las columnas en una tabla sea insignificante.

Si realmente tiene que hacer que se me ocurre una solución:

  • volcado y guardar la descripción de la tabla en cuestión (usando pg_dump --schema-only --table=<schema.table> ...)
  • añadir la columna que desea donde lo desee en la definición salvado
  • cambiar el nombre de la tabla en la definición guardan para no entrar en conflicto con el nombre de la mesa de edad cuando se intenta crearlo
  • crear la nueva tabla utilizando esta definición
  • llene la nueva tabla con los datos de la tabla anterior usando 'INSERT INTO <new_table> SELECCIONAR campo1, campo2, <default_for_new_field>, campo3, ... FROM <old_table>';
  • cambiar el nombre de la mesa de edad
  • cambiar el nombre de la nueva tabla al nombre original
  • finalmente caer el viejo, mesa rebautizado después de asegurarse de que todo está bien
+12

"cada consulta debe enumerar todos los campos que necesita en cualquier orden" → eso es fácil, siempre y cuando no tenga que trabajar con otros seres humanos. –

+9

Si bien el orden de las columnas puede ser irrelevante para una aplicación que utiliza la base de datos. Sería mucho mejor para un administrador de bases de datos si se enumeran columnas similares en orden cuando se investiga una estructura de tabla o datos. Personalmente me resulta molesto tener varias columnas temporales que no están agrupadas visualmente porque se agregaron más tarde. Volver a crear una base de datos solo porque Postgres no sea compatible con agregar una columna en una determinada posición me resulta extraño, especialmente si la razón detrás de esto es forzar a las personas a listar columnas explícitamente en sus consultas. Para ser claro: no creo que esa sea la razón. – Dynom

-3

El orden de las columnas es totalmente irrelevante en bases de datos relacionales

Sí.

Por ejemplo, si se utiliza Python, que haría:

cursor.execute("SELECT id, name FROM users") 
for id, name in cursor: 
    print id, name 

O puede hacer:

cursor.execute("SELECT * FROM users") 
for row in cursor: 
    print row['id'], row['name'] 

Pero ninguna persona en su sano juicio nunca utilizar los resultados de posición como esta:

cursor.execute("SELECT * FROM users") 
for id, name in cursor: 
    print id, name 
+9

Esto es totalmente falso. Eso funciona para seleccionar la forma en que se muestra, pero no es raro ver insertos sin los nombres de columna especificados, p. insertar en los valores de la tabla (1, 2, 3, 4). Si los ordinales de columna de la tabla cambian, ese estilo de consulta de inserción falla. También vale la pena señalar que no todos los desarrolladores están en su sano juicio y si heredas el código de uno de esos desarrolladores ... –

21

El orden de las columnas no es irrelevante, colocando columnas de ancho fijo al frente de la tabla puede optar por imite el diseño de almacenamiento de sus datos, también puede facilitar el trabajo con sus datos fuera del código de la aplicación.

PostgreSQL no admite la modificación del orden de las columnas (ver Alter column position en la wiki de PostgreSQL); si la tabla está relativamente aislada, lo mejor es volver a crear la tabla:

CREATE TABLE foobar_new (...); 
INSERT INTO foobar_new SELECT ... FROM foobar; 
DROP TABLE foobar CASCADE; 
ALTER TABLE foobar_new RENAME TO foobar; 

Si usted tiene una gran cantidad de puntos de vista o las limitaciones definidas en contra de la tabla, puede volver a agregar todas las columnas después de la nueva columna y suelta las columnas originales (mira la wiki de PostgreSQL para ver un ejemplo).

-1

@ La solución anterior de Jeemy Gustie casi funciona, pero hará lo incorrecto si los ordinales están desactivados (o fallan por completo si los ordinales reordenados hacen que los tipos incompatibles coincidan). Darle una oportunidad:

CREATE TABLE test1 (one varchar, two varchar, three varchar); 
CREATE TABLE test2 (three varchar, two varchar, one varchar); 
INSERT INTO test1 (one, two, three) VALUES ('one', 'two', 'three'); 
INSERT INTO test2 SELECT * FROM test1; 
SELECT * FROM test2; 

Los resultados muestran el problema:

testdb=> select * from test2; 
three | two | one 
-------+-----+------- 
one | two | three 
(1 row) 

Usted puede remediar esto especificando los nombres de columna en el inserto:

INSERT INTO test2 (one, two, three) SELECT * FROM test1; 

Eso le da lo que realmente quiero:

testdb=> select * from test2; 
three | two | one 
-------+-----+----- 
three | two | one 
(1 row) 

El problema viene cuando tienes un legado que no hace esto, como indiqué anteriormente en mi comentario sobre la respuesta de peufeu.

Actualización: Se me ocurrió que puede hacer lo mismo con los nombres de columna en la cláusula INSERT especificando los nombres de columna en la cláusula SELECT. Sólo tienes que cambiar su orden para que coincida con los ordinales en la tabla de destino:

INSERT INTO test2 SELECT three, two, one FROM test1; 

Y por supuesto, puedes hacer las dos cosas a ser muy explícito:

INSERT INTO test2 (one, two, three) SELECT one, two, three FROM test1; 

Eso le da los mismos resultados que el anterior, con los valores de columna correctamente emparejados.

-2

@ Milen A. Radev

La necesidad de tener un irrelevantes para conjunto de columnas no siempre se define por la consulta que tira de ellos. En los valores de pg_fetch_row no se incluye el nombre de columna asociado y, por lo tanto, requeriría que las columnas se definan mediante la instrucción de SQL.

Un simple select * from requeriría un conocimiento innato de la estructura de la tabla y, a veces, causaría problemas si el orden de las columnas cambiara.

El uso de pg_fetch_assoc es un método más confiable ya que puede hacer referencia a los nombres de las columnas y, por lo tanto, usar un simple select * from.

+1

Esta necesidad no es irrelevante. Cuando inspecciono los datos manualmente, quiero usar simplemente 'SELECT *' y, sin embargo, quiero que las columnas más interesantes estén primero. – maaartinus

Cuestiones relacionadas