Wie ändere ich die Position einer Spalte in einer PostgreSQL-Datenbanktabelle?

Antworten:

106

" Spaltenposition ändern " im PostgreSQL-Wiki sagt:

PostgreSQL definiert derzeit die Spaltenreihenfolge basierend auf der attnumSpalte der pg_attributeTabelle. Die einzige Möglichkeit, die Spaltenreihenfolge zu ändern, besteht darin, die Tabelle neu zu erstellen oder Spalten hinzuzufügen und Daten zu drehen, bis Sie das gewünschte Layout erreicht haben.

Das ist ziemlich schwach, aber zu ihrer Verteidigung gibt es in Standard-SQL auch keine Lösung für die Neupositionierung einer Spalte. Datenbankmarken, die das Ändern der Ordnungsposition einer Spalte unterstützen, definieren eine Erweiterung der SQL-Syntax.

Eine andere Idee fällt mir ein: Sie können eine definieren VIEW, die die Reihenfolge der Spalten nach Ihren Wünschen angibt, ohne die physische Position der Spalte in der Basistabelle zu ändern.

Bill Karwin
quelle
3
@Dana: Ich denke, das ist es, was im Wiki-Artikel unter "Neuerstellen der Tabelle" zu verstehen ist.
Bill Karwin
2
'Dump the Database' :: großartige Möglichkeit, Daten zu beschädigen. und daher den Effekt "Scrub the Massive Database".
Kent Fredric
31
@ Kent: Zweifellos leisten die Postgres-Entwickler einen langen Weg, um die Datenkonsistenz sicherzustellen, und das würde sicherlich für pg_dump gelten. Was bringt es, DB-Backups durchzuführen, wenn die Wiederherstellung fehlerhaft ist?
Dana the Sane
@Dana, ja, aber Sie fügen 1) einen großen Prozess zum Dumping hinzu, und dann fallen Sie ab, und dann haben Sie eine große zeitaufwändige Last. Wenn Sie eine haben ernsthaft massive Datenbank, die mit 37 Spalten in der Regel der Fall ist, Sie gehen Risiken im Zusammenhang mit Disk IO Würgen haben.
Kent Fredric
@DanatheSane das sind super alte Kommentare, aber was Bill sagte, ist im Wesentlichen dasselbe, anstatt einen vollständigen Datenbankspeicherauszug zu erstellen, müssen Sie nur die Tabelle (und die Abhängigkeiten) sichern, das Original löschen und dann neu erstellen. Sie müssen nicht die gesamte Datenbank offline schalten oder Zeit damit verbringen, etwas neu zu erstellen, das nicht betroffen ist. Auf der anderen Seite, wenn es viele Abhängigkeiten gibt, habe ich festgestellt, dass es viel einfacher ist, einen vollständigen Speicherauszug (wie Sie vorgeschlagen haben) durchzuführen.
Vol7ron
36

Wenn Sie in PostgreSQL ein Feld hinzufügen, wird es am Ende der Tabelle hinzugefügt. Wenn wir dann in eine bestimmte Position einfügen müssen

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;
Alle gewinnen
quelle
3
Wow das ist großartig, ich bin sicher, das sollte die akzeptierte Antwort sein!
Tommaso Thea Cioni
Ja, es ist wirklich hilfreich, vielen Dank!
Acuna
Sie können die aktuelle Tabelle auch wie folgt in eine neue alte Tabelle kopieren: CREATE TABLE oldtable AS SELECT * FROM tablename;
Ryan
29

Dieser Beitrag ist alt und wahrscheinlich gelöst, aber ich hatte das gleiche Problem. Ich habe es behoben, indem ich eine Ansicht der ursprünglichen Tabelle erstellt habe, in der die neue Spaltenreihenfolge angegeben ist.

Von hier aus könnte ich entweder die Ansicht verwenden oder eine neue Tabelle aus der Ansicht erstellen.

    CREATE VIEW original_tab_vw AS
    SELECT a.col1, a.col3, a.col4, a.col2
    FROM original_tab a
    WO a.col1 NICHT NULL IST - oder was auch immer
    SELECT * INTO new_table FROM original_tab_vw

Benennen Sie die ursprüngliche Tabelle um oder löschen Sie sie und setzen Sie den Namen der neuen Tabelle auf die alte Tabelle.

Ken
quelle
2
Dies scheint eine ziemlich vernünftige Lösung zu sein. Es ist schade, dass es keine GUI-Tools gibt, um diesen Vorgang zu automatisieren.
Quolonel Fragen
4
Gute Lösung, aber nur die Datentypen werden kopiert (kein Primärschlüssel usw.)
Regisz
1
Alternativ - verwenden Sie einfach die Ansicht mit den neu angeordneten Spalten wie sie sind. Es sollte eine minimale Leistungsverschlechterung geben.
pscl
1
Dies ist die beste Lösung.
Nikolay Shindarov
23

Eine, wenn auch umständliche Option, die Spalten neu anzuordnen, wenn die Spaltenreihenfolge unbedingt geändert werden muss und Fremdschlüssel verwendet werden, besteht darin, zuerst die gesamte Datenbank mit Daten zu sichern und dann nur das Schema ( pg_dump -s databasename > databasename_schema.sql) zu sichern . Bearbeiten Sie anschließend die Schemadatei, um die Spalten nach Ihren Wünschen neu anzuordnen. Erstellen Sie dann die Datenbank aus dem Schema neu und stellen Sie die Daten schließlich in der neu erstellten Datenbank wieder her.

Ville
quelle
1
Warum eine Ablehnung? In der akzeptierten Antwort heißt es im PostgreSQL-Wiki: »Die einzige Möglichkeit, die Spaltenreihenfolge zu ändern, besteht darin, die Tabelle neu zu erstellen oder Spalten hinzuzufügen und Daten zu drehen, bis Sie das gewünschte Layout erreicht haben.» Diese Lösung ist nicht optimal (keine dieser Antworten enthält keine integrierte Operation zur Ausführung der Aufgabe), bietet jedoch eine Möglichkeit, die Spalten in einer Tabelle neu anzuordnen.
Ville
1
Ich sage noch einmal, es gibt keine guten Möglichkeiten, dies zu tun, und was ich oben skizziere, ist eine gültige Möglichkeit, Spalten neu anzuordnen, wenn sie unbedingt neu angeordnet werden müssen. Wenn Sie meine Antwort ablehnen, kommentieren Sie bitte, warum Sie dies für eine inakzeptable Lösung halten.
Ville
3
In der Tat ist dies eine sehr gute Lösung, wenn die Tabelle in anderen Tabellen ein Fremdschlüssel ist. Alle anderen Lösungen funktionieren in diesem Szenario nicht. Verwenden Sie schließlich pg_dump - Spalte-Einfügungen -s Datenbankname> Datenbankname_schema.sql
Alejandro Salamanca Mazuelo
9

Ich glaube nicht, dass Sie das derzeit können: siehe diesen Artikel im Postgresql-Wiki .

Die drei Problemumgehungen in diesem Artikel sind:

  1. Erstellen Sie die Tabelle neu
  2. Spalten hinzufügen und Daten verschieben
  3. Verstecken Sie die Unterschiede mit einer Ansicht.
Mike Woodhouse
quelle
5

Öffnen Sie die Tabelle in PGAdmin und kopieren Sie im SQL-Bereich unten die SQL Create Table-Anweisung. Öffnen Sie dann das Abfrage-Tool und fügen Sie es ein. Wenn die Tabelle Daten enthält, ändern Sie den Tabellennamen in 'neuer_name'. Wenn nicht, löschen Sie den Kommentar "-" in der Zeile "Tabelle löschen". Bearbeiten Sie die Spaltenfolge nach Bedarf. Beachten Sie das fehlende / überflüssige Komma in der letzten Spalte, falls Sie es verschoben haben. Führen Sie den neuen SQL-Befehl Tabelle erstellen aus. Aktualisieren und ... voilà.

Für leere Tabellen in der Entwurfsphase ist diese Methode sehr praktisch.

Wenn die Tabelle Daten enthält, müssen wir auch die Spaltenfolge der Daten neu anordnen. Dies ist einfach: Verwenden Sie INSERTdiese Option, um die alte Tabelle in die neue Version zu importieren.

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

... wo c2, c3, c1sind die Säulen c1, c2, c3der alten Tabelle in ihren neuen Positionen. Bitte beachten Sie, dass Sie in diesem Fall einen 'neuen' Namen für die bearbeitete 'alte' Tabelle verwenden müssen, da Sie sonst Ihre Daten verlieren . Wenn die Spaltennamen zahlreich, lang und / oder komplex sind, verwenden Sie dieselbe Methode wie oben, um die neue Tabellenstruktur in einen Texteditor zu kopieren und dort die neue Spaltenliste zu erstellen, bevor Sie sie in die INSERTAnweisung kopieren .

Nachdem Sie überprüft haben, ob alles in Ordnung ist, DROPdie alte Tabelle und ändern Sie den 'neuen' Namen in 'alt' mit ALTER TABLE new RENAME TO old;und Sie sind fertig.

Marco Polo
quelle
1

Ich habe daran gearbeitet, viele Tabellen neu zu bestellen, und wollte nicht immer wieder dieselben Abfragen schreiben müssen, also habe ich ein Skript erstellt, um alles für mich zu erledigen. Im Wesentlichen ist es:

  1. Ruft die Tabellenerstellungs-SQL von ab pg_dump
  2. Ruft alle verfügbaren Spalten aus dem Speicherauszug ab
  3. Setzt die Spalten in die gewünschte Reihenfolge
  4. Ändert das Original pg_dump Abfrage, um eine neu geordnete Tabelle mit Daten zu erstellen
  5. Lässt alten Tisch fallen
  6. Benennt die neue Tabelle um, um sie an die alte Tabelle anzupassen

Es kann verwendet werden, indem der folgende einfache Befehl ausgeführt wird:

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

Es druckt die SQL aus, damit Sie sie überprüfen und testen können. Das war ein wichtiger Grund, warum ich sie verwendet habe pg_dump. Das Github Repo finden Sie hier .

GammaGames
quelle
0

Ich benutze Django und es erfordert eine ID-Spalte in jeder Tabelle, wenn Sie keine Kopfschmerzen haben möchten. Leider war ich nachlässig und meine Tabelle bp.geo_location_vague enthielt dieses Feld nicht. Ich habe einen kleinen Trick paraphiert. Schritt 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

Schritt 2: (ohne Tabelle erstellen - Tabelle wird automatisch erstellt!)

SELECT * into bp.geo_location_vague_cp2 FROM bp.geo_location_vague_vw

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

Weil ich einen großen Pseudotyp in der Tabelle haben muss. Nach SELECT * in pg wird ein Bigint-Typ-Insetad-Bigserial erstellt.

Schritt 4: Jetzt können wir die Ansicht löschen, die Quelltabelle löschen und die neue Tabelle im alten Namen umbenennen. Der Trick wurde erfolgreich beendet.

Orlov Const
quelle