Domanda

È possibile cambiare l'ordine naturale delle colonne in Postgres 8.1?

So che non dovresti fare affidamento sull'ordine delle colonne - non è essenziale a quello che sto facendo - ne ho solo bisogno per far uscire alcune cose generate automaticamente in un modo che è più piacevole, in modo che l'ordine dei campi corrisponda completamente da pgadmin attraverso il back-end e fino al front-end.

È stato utile?

Soluzione

In realtà puoi semplicemente cambiare l'ordine delle colonne, ma difficilmente lo consiglierei e dovresti stare molto attento se decidi di farlo.

ad es.

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

Ora per la parte più delicata, è necessario connettersi al database utilizzando l'utente postgres in modo da poter modificare le tabelle di 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 è una colonna univoca, quindi è necessario utilizzare un valore temporaneo quando si modificano i numeri di colonna in quanto tali:

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

Ancora una volta, poiché si sta giocando con le tabelle di sistema del database, usare estrema cautela se ritieni di aver davvero bisogno di farlo.

Funziona a partire da Postgres 8.3, con le versioni precedenti, il tuo chilometraggio può variare.

Altri suggerimenti

Se il tuo database non è molto grande e puoi permetterti dei tempi di inattività, puoi:

  1. Disabilita l'accesso in scrittura al database
    questo è essenziale poiché in caso contrario qualsiasi modifica dopo l'inizio del punto successivo andrà persa
  2. pg_dump --create --column-inserts databasename > databasename.pgdump.sql
  3. Modifica l'istruzione CREATE TABLE appropriata in databasename.pgdump.sql
    Se il file è troppo grande per il tuo editor, basta dividerlo utilizzando il comando split , modificare, quindi assemblare nuovamente utilizzando cat
  4. elimina nome database database
    Hai un backup recente, per ogni evenienza, vero?
  5. psql --single-transazione -f databasename.pgdump.sql
    Se non usi --single-transazione sarà molto lento

Se usi i cosiddetti oggetti di grandi dimensioni assicurati che siano inclusi nel dump. Non sono sicuro che siano di default in 8.1.

Ho fatto questa domanda in pgsql-admin nel 2007. Tom Lane stesso ha dichiarato praticamente impossibile cambiare l'ordine nei cataloghi.

Chiarimento: per gli utenti, con gli strumenti attuali. Non significa che non potrebbe essere implementato. IMO, dovrebbe essere.
Ancora vero per Postgres 11.

Come indicato nelle altre risposte, non è possibile modificare l'ordine delle colonne, dipende da Postgres. Puoi (e dovresti!) Risolvere il tuo problema con una vista. Ai fini della tua query sui rapporti, sembrerà proprio come una tabella. Qualcosa del tipo:

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

Specificare l'ordine delle colonne nella query è l'unico modo affidabile (e sensato) . Detto questo, di solito è possibile ottenere un ordine diverso modificando la tabella come mostrato nell'esempio di seguito poiché le colonne di solito (non è garantito che vengano restituite) nell'ordine in cui sono state aggiunte alla tabella.

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

Sfortunatamente no, non lo è. L'ordine delle colonne dipende interamente da Postgres.

Puoi ottenere l'ordine delle colonne desiderato creando una nuova tabella e selezionando le colonne della vecchia tabella nell'ordine in cui desideri che vengano presentate:

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

Nota che questo copia solo dati, non modificatori, vincoli, indici, ecc.

Dopo aver modificato la nuova tabella nel modo desiderato, rilasciare l'originale e modificare il nome di quello nuovo:

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

Voglio lo stesso. Sì, ordina ora essenziale, ma mi sfrega nel modo sbagliato :)

Quello che sto facendo per risolverlo è il seguente.

Questo metodo ti garantirà di MANTENERE tutti i dati esistenti,

  1. Crea una nuova versione della tabella usando l'ordine che desidero, usando un nome temporaneo.
  2. Inserisci tutti i dati in quella nuova tabella da quella esistente.
  3. Elimina il vecchio tavolo.
  4. Rinomina la nuova tabella con il "nome proprio" da " nome temporaneo " ;.
  5. Aggiungi nuovamente tutti gli indici che avevi in ??precedenza.
  6. Ripristina sequenza ID per incrementi di chiave primaria.

Ordine tabella corrente:

id, name, email

1. Crea una nuova versione della tabella utilizzando l'ordinamento desiderato, utilizzando un nome temporaneo.

In questo esempio, voglio email prima di name .

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

2. Inserisci tutti i dati in quella nuova tabella da quella esistente.

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

3. Elimina il vecchio tavolo.

DROP TABLE mytable;

4. Rinomina la nuova tabella con il "nome proprio" da " nome temporaneo " ;.

ALTER TABLE mytable_tmp RENAME TO mytable;

5. Aggiungi nuovamente tutti gli indici che avevi in ??precedenza.

CREATE INDEX ...

6. Reimposta sequenza ID per incrementi di chiave primaria.

SELECT setval('public.mytable_id_seq', max(id)) FROM mytable;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top