web-dev-qa-db-fra.com

Comment ajouter une clé primaire auto-incrémentée à une table existante, dans PostgreSQL?

J'ai une table avec des données existantes. Est-il possible d'ajouter une clé primaire sans supprimer ni recréer la table?

167
xRobot

(Mise à jour - Merci aux personnes qui ont commenté)

Versions modernes de PostgreSQL

Supposons que vous ayez une table nommée test1, à laquelle vous souhaitez ajouter une colonne de clé primaire id à incrémentation automatique. La commande suivante devrait suffire dans les versions récentes de PostgreSQL:

   ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

Anciennes versions de PostgreSQL

Dans les anciennes versions de PostgreSQL (antérieures à la version 8.x?), Vous deviez faire tout le sale boulot. La séquence de commandes suivante devrait faire l'affaire:

  ALTER TABLE test1 ADD COLUMN id INTEGER;
  CREATE SEQUENCE test_id_seq OWNED BY test1.id;
  ALTER TABLE test ALTER COLUMN id SET DEFAULT nextval('test_id_seq');
  UPDATE test1 SET id = nextval('test_id_seq');

Encore une fois, dans les versions récentes de Postgres, cela équivaut à peu près à la commande unique ci-dessus.

310
leonbloy
ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

C'est tout ce dont vous avez besoin pour:

  1. Ajouter la colonne id
  2. Remplissez-le avec une séquence de 1 à compter (*).
  3. Définissez-le comme clé primaire/non null.

Nous remercions @resnyanskiy qui a donné cette réponse dans un commentaire.

47
Synesso

Pour utiliser une colonne d'identité dans la v10,

ALTER TABLE test 
ADD COLUMN id { int | bigint | smallint}
GENERATED { BY DEFAULT | ALWAYS } AS IDENTITY PRIMARY KEY;

Pour une explication des colonnes d'identité, voir https://blog.2ndquadrant.com/postgresql-10-identity-columns/ .

Pour connaître la différence entre GENERATED BY DEFAULT et GENERATED TOUJOURS, voir https://www.cybertec-postgresql.com/fr/sequences-gains-and-pitfalls/ .

Pour modifier la séquence, voir https://popsql.io/learn-sql/postgresql/how-to-alter-sequence-in-postgresql/ .

6
jhoanna

J'ai atterri ici parce que je cherchais quelque chose comme ça aussi. Dans mon cas, je copiais les données d'un ensemble de tables de transfert avec plusieurs colonnes dans une seule table tout en affectant des identifiants de ligne à la table cible. Voici une variante des approches ci-dessus que j'ai utilisées. J'ai ajouté la colonne de série à la fin de ma table cible. De cette façon, je n'ai pas besoin d'un espace réservé pour cela dans la déclaration Insert. Ensuite, une simple sélection * dans la table cible est automatiquement renseignée dans cette colonne. Voici les deux instructions SQL que j'ai utilisées sous PostgreSQL 9.6.4.

ALTER TABLE target ADD COLUMN some_column SERIAL;
INSERT INTO target SELECT * from source;
2
Dean Sha