Come posso modificare la posizione di una colonna in una tabella di database PostgreSQL?


Risposte:


107

" Alter column position " nel Wiki di PostgreSQL dice:

PostgreSQL attualmente definisce l'ordine delle colonne in base alla attnumcolonna della pg_attributetabella. L'unico modo per modificare l'ordine delle colonne è ricreare la tabella o aggiungere colonne e ruotare i dati fino a raggiungere il layout desiderato.

È piuttosto debole, ma a loro difesa, nell'SQL standard, non esiste nemmeno una soluzione per riposizionare una colonna. I marchi di database che supportano la modifica della posizione ordinale di una colonna stanno definendo un'estensione della sintassi SQL.

Mi viene in mente un'altra idea: puoi definire un VIEWche specifica l'ordine delle colonne come preferisci, senza cambiare la posizione fisica della colonna nella tabella di base.


3
@ Dana: Penso che questo sia ciò che si intende per "ricreare la tabella" nell'articolo wiki.
Bill Karwin,

2
'dump the database' :: ottimo modo per danneggiare i dati. e quindi l'effetto "strofina l'enorme database".
Kent Fredric

31
@ Kent: Dubbioso, gli sviluppatori di postgres fanno molto per garantire la coerenza dei dati e questo si applicherebbe sicuramente a pg_dump. Dopotutto, qual è il punto di fare backup db se il ripristino è interrotto?
Dana the Sane

@Dana, sì, ma stai aggiungendo 1) un grande processo da scaricare, e poi lo lasci cadere, e poi hai un grande carico di tempo. Se avete un serio enorme database, che di solito è il caso con 37 colonne, si sta andando ad avere rischi con IO disco soffocamento.
Kent Fredric

@DanatheSane questi sono commenti super vecchi , ma quello che Bill stava dicendo è essenzialmente la stessa cosa, invece di eseguire un dump completo del database, devi solo scaricare la tabella (e le dipendenze), uccidere l'originale, quindi ricreare. Non è necessario portare offline l'intero database o perdere tempo a ricreare qualcosa che non è interessato. D'altra parte, se ci sono molte dipendenze, ho scoperto che eseguire un dump completo (come suggerito) è molto più semplice.
vol7ron

37

In PostgreSQL, aggiungendo un campo sarebbe stato aggiunto alla fine della tabella. Se dobbiamo inserire in una posizione particolare, allora

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;

4
Wow, è fantastico, sono sicuro che questa dovrebbe essere la risposta accettata!
Tommaso Thea Cioni

Sì, è davvero utile, grazie mille!
Acuna

È anche possibile copiare la tabella corrente in una nuova vecchia tabella in questo modo: CREATE TABLE oldtable AS SELECT * FROM tablename;
Ryan

29

Questo post è vecchio e probabilmente risolto ma ho avuto lo stesso problema. L'ho risolto creando una vista della tabella originale che specifica il nuovo ordine delle colonne.

Da qui potrei usare la vista o creare una nuova tabella dalla vista.

    CREA VISTA original_tab_vw AS
    SELEZIONA a.col1, a.col3, a.col4, a.col2
    FROM original_tab a
    DOVE a.col1 NON È NULLO o qualsiasi altra cosa
    SELEZIONA * NELLA new_table FROM original_tab_vw

Rinomina o rilascia la tabella originale e imposta il nome della nuova tabella sulla vecchia tabella.


2
Questa sembra una soluzione abbastanza ragionevole. Peccato che non ci siano strumenti GUI per automatizzare questa procedura.
Domande Quolonel

4
buona soluzione ma vengono copiati solo i tipi di dati (nessuna chiave primaria, ecc.)
Regisz

1
In alternativa, usa la vista con le colonne riordinate così come sono. Ci dovrebbe essere una riduzione minima delle prestazioni.
pscl

1
Questa è la soluzione migliore.
Nikolay Shindarov,

23

Una, sebbene un'opzione goffa per riorganizzare le colonne quando l'ordine delle colonne deve essere assolutamente modificato e le chiavi esterne sono in uso, è prima eseguire il dump dell'intero database con i dati, quindi eseguire il dump solo dello schema ( pg_dump -s databasename > databasename_schema.sql). Quindi modifica il file dello schema per riorganizzare le colonne come desideri, quindi ricrea il database dallo schema e infine ripristina i dati nel database appena creato.


1
Perché un voto negativo? Come sottolinea la risposta accettata, citando il Wiki di PostgreSQL: »L'unico modo per cambiare l'ordine delle colonne è ricreare la tabella o aggiungere colonne e ruotare i dati fino a raggiungere il layout desiderato.» Questa soluzione non è ottimale (nessuna di queste risposte è in assenza di un'operazione incorporata per eseguire l'attività), ma fornisce un modo per riorganizzare le colonne in una tabella.
Ville

1
Lo ripeto, non ci sono buoni modi per farlo, e quello che ho delineato sopra è un modo valido per riorganizzare le colonne se devono assolutamente essere riorganizzate. Se dai un voto negativo alla mia risposta, commenta perché ritieni che sia una soluzione inaccettabile.
Ville

3
In effetti, questa è un'ottima soluzione quando la tabella è una chiave esterna in un'altra tabella. Tutte le altre soluzioni non funzionano in questo escenario. Infine, usa pg_dump --column-inserts -s databasename> databasename_schema.sql
Alejandro Salamanca Mazuelo


5

Aprire la tabella in PGAdmin e nel riquadro SQL in basso copiare l'istruzione SQL Create Table. Quindi apri lo Strumento di query e incolla. Se la tabella contiene dati, modificare il nome della tabella in "new_name", altrimenti eliminare il commento "-" nella riga Drop Table. Modificare la sequenza di colonne come richiesto. Attenzione alla virgola mancante / superflua nell'ultima colonna nel caso l'avessi spostata. Eseguire il nuovo comando SQL Crea tabella. Aggiorna e ... voilà.

Per le tabelle vuote in fase di progettazione questo metodo è abbastanza pratico.

Nel caso in cui la tabella contenga dati, è necessario riorganizzare anche la sequenza delle colonne dei dati. Questo è facile: usa INSERTper importare la vecchia tabella nella sua nuova versione con:

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

... dove c2, c3, c1sono le colonne c1, c2, c3della vecchia tabella nelle loro nuove posizioni. Tieni presente che in questo caso devi utilizzare un "nuovo" nome per la "vecchia" tabella modificata, altrimenti perderai i tuoi dati . Nel caso in cui i nomi delle colonne siano molti, lunghi e / o complessi, utilizzare lo stesso metodo di cui sopra per copiare la nuova struttura della tabella in un editor di testo e creare lì il nuovo elenco di colonne prima di copiarlo INSERTnell'istruzione.

Dopo aver verificato che tutto sia a posto, DROPla vecchia tabella cambia il nome "nuovo" in "vecchio" ALTER TABLE new RENAME TO old;e il gioco è fatto.


1

Stavo lavorando al riordino di molte tabelle e non volevo dover scrivere le stesse query più e più volte, quindi ho creato uno script per fare tutto per me. In sostanza:

  1. Ottiene l'SQL di creazione della tabella da pg_dump
  2. Ottiene tutte le colonne disponibili dal dump
  3. Mette le colonne nell'ordine desiderato
  4. Modifica la pg_dumpquery originale per creare una tabella riordinata con i dati
  5. Gocce vecchio tavolo
  6. Rinomina la nuova tabella in modo che corrisponda alla vecchia tabella

Può essere utilizzato eseguendo il seguente semplice comando:

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

Stampa lo sql in modo che tu possa verificarlo e testarlo, questo è stato un grande motivo su cui l'ho basato pg_dump. Puoi trovare il repository GitHub qui .


0

Uso Django e richiede una colonna id in ogni tabella se non vuoi avere mal di testa. Sfortunatamente, sono stato distratto e la mia tabella bp.geo_location_vague non conteneva questo campo. Ho siglato un piccolo trucco. Passo 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

Passaggio 2: (senza creare tabella, la tabella creerà automaticamente!)

SELECT * into bp.geo_location_vague_cp2 FROM bp.geo_location_vague_vw

Passaggio 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;

Perché ho bisogno di avere uno pseudotipo bigserial nella tabella. Dopo SELECT * in pg creerà il tipo bigint insetad bigserial.

passo 4: Ora possiamo eliminare la vista, rilasciare la tabella di origine e rinominare la nuova tabella con il vecchio nome. Il trucco è stato risolto con successo.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.