2009-08-07 19 views
44

Come aggiungere una nuova colonna in una tabella dopo la 2a o 3a colonna nella tabella utilizzando Postgres?Come aggiungere una nuova colonna in una tabella dopo la 2a o 3a colonna nella tabella usando postgres?

Il mio codice si presenta come segue

ALTER TABLE n_domains ADD COLUMN contract_nr int after owner_id 
+2

L'ordine delle colonne è totalmente irrilevante nei database relazionali - è solo questione di visualizzarli in uno strumento. La tabella del database non ha alcun ordinamento delle colonne. –

risposta

49

No, non c'è alcun modo diretto per farlo. E c'è una ragione: ogni query dovrebbe elencare tutti i campi di cui ha bisogno in qualsiasi ordine (e formato ecc.) Di cui ha bisogno, rendendo così l'ordine delle colonne in una tabella insignificante.

Se avete veramente bisogno di fare che mi viene in mente una soluzione:

  • discarica e salvare la descrizione della tabella in questione (utilizzando pg_dump --schema-only --table=<schema.table> ...)
  • aggiungere la colonna che si desidera dove vuoi nella definizione salvata
  • rinominare la tabella nella definizione salvato in modo da non scontrarsi con il nome della vecchia tabella quando si tenta di crearlo
  • creare la nuova tabella utilizzando questa definizione
  • popola la nuova tabella con i dati della vecchia tabella utilizzando 'INSERT INTO <new_table> SELECT field1, field2, <default_for_new_field>, field3, ... FROM <old_table>';
  • rinominare la vecchia tabella
  • rinominare la nuova tabella al nome originale
  • finalmente cadere il vecchio, tavolo rinominato dopo aver apportato che tutto sia a posto
+12

"ogni query dovrebbe elencare tutti i campi di cui ha bisogno in qualsiasi ordine" → è facile, a patto che non si debba mai lavorare con altri esseri umani. –

+9

Mentre l'ordine delle colonne potrebbe essere irrilevante per un'applicazione che utilizza il database. Sarebbe molto più bello per un DBA se le colonne simili sono elencate in ordine per indagare su una struttura o dati di una tabella. Personalmente trovo fastidioso avere diverse colonne temporali che non sono raggruppate visivamente perché sono state aggiunte in seguito. Ricreare un database solo perché Postgres non supporta l'aggiunta di una colonna in una determinata posizione mi sembra strano, specialmente se la ragione di ciò è forzare le persone ad elencare le colonne esplicitamente nelle loro query. Per essere chiari: non credo che questo sia il motivo. – Dynom

-3

L'ordine delle colonne è del tutto irrilevante in database relazionali

Sì.

Per esempio, se si utilizza Python, si dovrebbe fare:

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

O si dovrebbe fare:

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

Ma nessuna persona sana di mente avrebbe mai utilizzare i risultati di posizione come questo:

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

Questo è totalmente falso. Ciò funziona per selezionare il modo in cui stai mostrando, ma non è raro vedere gli inserti senza i nomi delle colonne specificati, ad es. inserire nei valori della tabella (1, 2, 3, 4). Se le ordinali delle colonne della tabella cambiano, lo stile della query di inserimento non riesce. Vale anche la pena notare che non tutti gli sviluppatori sono sani di mente e se capita di ereditare codice da uno di quegli sviluppatori ... –

21

L'ordine delle colonne non è irrilevante, mettendo colonne di larghezza fissa nella parte anteriore del tavolo può optare Imize il layout di archiviazione dei dati, può anche rendere più facile lavorare con i dati al di fuori del codice dell'applicazione.

PostgreSQL non supporta l'alterazione dell'ordine delle colonne (vedere Alter column position nel wiki PostgreSQL); se la tabella è relativamente isolato, la soluzione migliore è quella di ricreare la tabella:

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

Se avete un sacco di punti di vista o vincoli definiti contro il tavolo, è possibile aggiungere nuovamente tutte le colonne dopo la nuova colonna e rilascia le colonne originali (vedi il wiki PostgreSQL per un esempio).

-1

@Jeremy La soluzione di Gustie sopra funziona quasi, ma farà la cosa sbagliata se gli ordinali sono spenti (o falliscono del tutto se gli ordinali riordinati corrispondono a tipi incompatibili). Fate una prova:

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; 

I risultati mostrano il problema:

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

È possibile rimediare a questo specificando i nomi delle colonne nell'inserto:

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

Che ti dà quello che ti vuole veramente:

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

Il problema si presenta quando si ha legacy che non lo fa, come ho indicato sopra nel mio commento sulla risposta di Peufeu.

Aggiornamento: Mi è venuto in mente che è possibile fare la stessa cosa con i nomi delle colonne nella clausola INSERT specificando i nomi delle colonne nella clausola SELECT. Devi solo riordinarli per abbinare gli ordinali nella tabella di destinazione:

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

E si può ovviamente fare entrambe di essere molto esplicito:

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

Che ti dà gli stessi risultati di cui sopra, con i valori della colonna correttamente abbinati.

-2

@ Milen A. Radev

La necessità irrilevante da avere un ordine insieme di colonne non è sempre definita dalla query che li tira. Nei valori da pg_fetch_row non include il nome di colonna associato e pertanto richiederebbe che le colonne siano definite dall'istruzione SQL.

Un semplice select * from richiederebbe una conoscenza innata della struttura della tabella e talvolta causerebbe problemi se l'ordine delle colonne dovesse cambiare.

L'utilizzo di pg_fetch_assoc è un metodo più affidabile in quanto è possibile fare riferimento ai nomi delle colonne e quindi utilizzare un semplice select * from.

+1

Questa esigenza non è irrilevante. Quando controllo i dati manualmente, voglio usare semplicemente "SELECT *" e tuttavia voglio che le colonne più interessanti vengano prima. – maaartinus

Problemi correlati