Comment modifier la position d'une colonne dans une table de base de données PostgreSQL?

Réponses:

107

" Modifier la position de la colonne " dans le wiki PostgreSQL dit:

PostgreSQL définit actuellement l'ordre des colonnes en fonction de la attnumcolonne de la pg_attributetable. La seule façon de modifier l'ordre des colonnes consiste soit à recréer le tableau, soit à ajouter des colonnes et à faire pivoter les données jusqu'à ce que vous atteigniez la disposition souhaitée.

C'est assez faible, mais pour leur défense, en SQL standard, il n'y a pas non plus de solution pour repositionner une colonne. Les marques de base de données qui prennent en charge la modification de la position ordinale d'une colonne définissent une extension de la syntaxe SQL.

Une autre idée me vient à l'esprit: vous pouvez définir un VIEWqui spécifie l'ordre des colonnes comme vous l'aimez, sans changer la position physique de la colonne dans la table de base.

Bill Karwin
la source
3
@Dana: Je pense que c'est ce que signifie "recréer la table" dans l'article du wiki.
Bill Karwin
2
'vider la base de données' :: excellent moyen d'endommager les données. et par conséquent "nettoyer la base de données massive".
Kent Fredric
31
@Kent: Doute, les développeurs de postgres vont un long chemin pour assurer la cohérence des données et cela s'appliquerait certainement à pg_dump. Après tout, quel est l'intérêt de faire des sauvegardes de base de données si la restauration est interrompue?
Dana the Sane
@Dana, oui, mais vous ajoutez 1) un gros processus de vidage, puis vous abandonnez, et puis vous avez une grosse charge de temps. Si vous avez une base de données très massive, ce qui est généralement le cas avec 37 colonnes, vous allez avoir des risques d'étouffement d'E / S disque.
Kent Fredric
@DanatheSane ce sont de super vieux commentaires, mais ce que Bill disait est essentiellement la même chose, au lieu de faire un vidage complet de la base de données, vous visez simplement la table (et les dépendances), tuez l'original, puis recréez. Pas besoin de mettre toute la base de données hors ligne ou de passer du temps à recréer quelque chose qui n'est pas affecté. D'un autre côté, s'il y a beaucoup de dépendances, j'ai trouvé qu'il était beaucoup plus facile de faire un vidage complet (comme vous l'avez suggéré).
vol7ron
37

Dans PostgreSQL, lors de l'ajout d'un champ, il serait ajouté à la fin de la table. Si nous devons insérer dans une position particulière, alors

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;
Allwin
la source
4
Wow c'est génial, je suis sûr que cela devrait être la réponse acceptée!
Tommaso Thea Cioni
Ouais, c'est vraiment utile, merci beaucoup!
Acuna
Vous pouvez également copier la table actuelle dans une nouvelle ancienne table comme ceci: CREATE TABLE oldtable AS SELECT * FROM nomtable;
Ryan le
29

Ce message est ancien et probablement résolu mais j'ai eu le même problème. Je l'ai résolu en créant une vue de la table d'origine spécifiant le nouvel ordre des colonnes.

De là, je pourrais utiliser la vue ou créer une nouvelle table à partir de la vue.

    CRÉER UNE VUE original_tab_vw AS
    SELECT a.col1, a.col3, a.col4, a.col2
    FROM original_tab a
    O a.col1 N'EST PAS NULL - ou quoi que ce soit
    SELECT * INTO new_table FROM original_tab_vw

Renommez ou supprimez la table d'origine et définissez le nom de la nouvelle table sur l'ancienne table.

Ken
la source
2
Cela semble être une solution assez raisonnable. C'est dommage qu'il n'y ait pas d'outils GUI pour automatiser cette procédure.
Questions Quolonel
4
bonne solution mais seuls les types de données sont copiés (pas de clé primaire, etc.)
Regisz
1
Sinon, utilisez simplement la vue avec les colonnes réorganisées telles quelles. Il devrait y avoir une dégradation minimale des performances.
pscl
1
C'est la meilleure solution.
Nikolay Shindarov le
23

Une option, bien que maladroite, pour réorganiser les colonnes lorsque l'ordre des colonnes doit absolument être changé et que des clés étrangères sont utilisées, consiste à d'abord vider la base de données entière avec les données, puis à vider uniquement le schéma ( pg_dump -s databasename > databasename_schema.sql). Modifiez ensuite le fichier de schéma pour réorganiser les colonnes comme vous le souhaitez, puis recréez la base de données à partir du schéma et restaurez enfin les données dans la base de données nouvellement créée.

Ville
la source
1
Pourquoi un vote négatif? Comme le souligne la réponse acceptée, citant le wiki PostgreSQL: »La seule façon de changer l'ordre des colonnes est soit de recréer la table, soit en ajoutant des colonnes et en faisant pivoter les données jusqu'à ce que vous atteigniez la mise en page souhaitée.» Cette solution n'est pas optimale (aucune de ces réponses n'est en l'absence d'une opération intégrée pour accomplir la tâche), mais elle fournit un moyen de réorganiser les colonnes d'un tableau.
Ville
1
Je le répète, il n'y a pas de bons moyens de le faire, et ce que je décris ci - dessus est un moyen valable de réorganiser les colonnes si elles doivent absolument être réorganisées. Si vous refusez ma réponse, veuillez expliquer pourquoi vous estimez que c'est une solution inacceptable.
Ville
3
En fait, c'est une très bonne solution lorsque la table est une clé étrangère dans une autre table. Toutes les autres solutions ne fonctionnent pas dans cet escenario. Enfin, utilisez pg_dump --column-inserts -s databasename> databasename_schema.sql
Alejandro Salamanca Mazuelo
9

Je ne pense pas que vous le puissiez pour le moment: voir cet article sur le wiki PostgreSQL .

Les trois solutions de contournement de cet article sont:

  1. Recréez la table
  2. Ajouter des colonnes et déplacer des données
  3. Cachez les différences avec une vue.
Mike Woodhouse
la source
5

Ouvrez la table dans PGAdmin et dans le volet SQL en bas, copiez l'instruction SQL Create Table. Ensuite, ouvrez l'éditeur de requêtes et collez. Si la table contient des données, remplacez le nom de la table par «nouveau_nom», sinon supprimez le commentaire «-» dans la ligne Drop Table. Modifiez la séquence de colonnes selon vos besoins. Faites attention à la virgule manquante / superflue dans la dernière colonne au cas où vous l'auriez déplacée. Exécutez la nouvelle commande SQL Create Table. Rafraîchissez-vous et ... voilà.

Pour les tables vides au stade de la conception, cette méthode est assez pratique.

Si la table contient des données, nous devons également réorganiser la séquence des colonnes des données. C'est simple: utilisez INSERTpour importer l'ancienne table dans sa nouvelle version avec:

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

... où c2, c3, c1sont les colonnes c1, c2, c3de la vieille table dans leurs nouvelles fonctions. Veuillez noter que dans ce cas, vous devez utiliser un «nouveau» nom pour la table «ancienne» modifiée, sinon vous perdrez vos données . Dans le cas où les noms de colonnes sont nombreux, longs et / ou complexes, utilisez la même méthode que ci-dessus pour copier la nouvelle structure de table dans un éditeur de texte et créez-y la nouvelle liste de colonnes avant de la copier dans l' INSERTinstruction.

Après avoir vérifié que tout va bien, DROPutilisez l'ancienne table et changez le nom «nouveau» en «ancien» ALTER TABLE new RENAME TO old;et vous avez terminé.

Marco Polo
la source
1

Je travaillais à réorganiser de nombreuses tables et je ne voulais pas avoir à écrire les mêmes requêtes encore et encore, alors j'ai créé un script pour tout faire pour moi. Essentiellement, il:

  1. Obtient le SQL de création de table à partir de pg_dump
  2. Obtient toutes les colonnes disponibles à partir du vidage
  3. Place les colonnes dans l'ordre souhaité
  4. Modifie la pg_dumprequête d' origine pour créer une table réorganisée avec des données
  5. Supprime l'ancienne table
  6. Renomme la nouvelle table pour qu'elle corresponde à l'ancienne

Il peut être utilisé en exécutant la commande simple suivante:

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

Il imprime le sql afin que vous puissiez le vérifier et le tester, c'est une grande raison sur laquelle je l'ai basé pg_dump. Vous pouvez trouver le dépôt github ici .

GammaGames
la source
0

J'utilise Django et il nécessite une colonne id dans chaque table si vous ne voulez pas avoir mal à la tête. Malheureusement, j'étais imprudent et ma table bp.geo_location_vague ne contenait pas ce champ. J'ai paraphé un petit truc. Étape 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

Étape 2: (sans créer de table - la table se créera automatiquement!)

SELECT * into bp.geo_location_vague_cp2 FROM bp.geo_location_vague_vw

Étape 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;

Parce que j'ai besoin d'un pseudotype bigserial dans le tableau. Après SELECT * dans pg, vous créerez le type bigint insetad bigserial.

étape 4: Nous pouvons maintenant supprimer la vue, supprimer la table source et renommer la nouvelle table avec l'ancien nom. L'astuce s'est terminée avec succès.

Orlov Const
la source