Come aggiungere una chiave primaria a incremento automatico a una tabella esistente, in PostgreSQL?


Risposte:


355

( Aggiornato - Grazie alle persone che hanno commentato )

Versioni moderne di PostgreSQL

Supponiamo di avere una tabella denominata test1, alla quale si desidera aggiungere una idcolonna con chiave primaria (surrogata) ad incremento automatico . Il seguente comando dovrebbe essere sufficiente nelle versioni recenti di PostgreSQL:

   ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

Versioni precedenti di PostgreSQL

Nelle vecchie versioni di PostgreSQL (precedenti alla 8.x?) Dovevi fare tutto il lavoro sporco. La seguente sequenza di comandi dovrebbe fare il trucco:

  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');

Ancora una volta, nelle recenti versioni di Postgres questo è approssimativamente equivalente al singolo comando sopra.


3
Sto usando ORACLE, quindi la condivisione potrebbe essere utile per i ragazzi di ORACLE In ORACLE: ALTER TABLE TEST1 AGGIUNGI NUMERO ID; UPDATE TEST1 SET ID = TEST1_SEQ.NEXTVAL; ALTER TABLE TEST1 AGGIUNGI TASTO PRIMARIO (ID); creare una sequenza TEST1_SEQ prima di eseguire l'istruzione UPDATE
msbyuva,

Si noti che ADD PRIMARY KEYcrea anche un NOT NULLvincolo (testato in Postgres 9.3) come previsto e desiderato.
Jared Beck,

19
In Postgres puoi usare il comando singoloALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;
resnyanskiy,

1
Oltre al commento di @ resnyanskiy, questo funzionerà anche quando ci sono dati nella tabella. Gli ID vengono popolati e non è impostato un vincolo nullo. L'intera risposta può essere sostituita dalla riga in quel commento.
Synesso,

1
@EricWang Grazie, Eric, hai ragione - credo che non abbia funzionato alcune versioni (anni) fa, ma non ne sono sicuro. Trasformato la risposta in wiki della community.
leonbloy,

57
ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

Questo è tutto ciò che serve per:

  1. Aggiungi la idcolonna
  2. Compilalo con una sequenza da 1 a contare (*).
  3. Impostalo come chiave primaria / non null.

Il merito è dato a @resnyanskiy che ha dato questa risposta in un commento.


2
Questo dovrebbe essere contrassegnato come risposta e la risposta dovrebbe appartenere a @resnyanskiy
Eric Wang

Ho dovuto prima rilasciare la chiave e quindi eseguire questo. ALTER TABLE <table> DROP CONSTRAINT <pkey_name>;
Josh Robertson,

10

Per utilizzare una colonna identità in v10,

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

Per una spiegazione delle colonne di identità, consultare https://blog.2ndquadrant.com/postgresql-10-identity-columns/ .

Per la differenza tra GENERATED BY DEFAULT e GENERATED SEMPRE, consultare https://www.cybertec-postgresql.com/en/sequences-gains-and-pitfalls/ .

Per modificare la sequenza, vedere https://popsql.io/learn-sql/postgresql/how-to-alter-sequence-in-postgresql/ .


Il problema con questa soluzione è che se la tabella contiene già righe, viene visualizzato un errore:SQL Error [23502]: ERROR: column "id" contains null values
isapir

3
@isapir: c'era un bug nelle prime versioni (pag. 10 e 10.1) che produceva questo errore. È stato corretto con pg 10.2. Dettagli qui: dba.stackexchange.com/q/200143/3684
Erwin Brandstetter

Grazie @ erwin-brandstetter
isapir

Un anno dopo ho trovato di nuovo questa risposta, apparentemente corretto, corretto;)
isapir

2

Sono atterrato qui perché stavo cercando qualcosa del genere. Nel mio caso, stavo copiando i dati da una serie di tabelle di gestione temporanea con molte colonne in una tabella mentre assegnavo anche gli ID di riga alla tabella di destinazione. Ecco una variante degli approcci sopra che ho usato. Ho aggiunto la colonna seriale alla fine della mia tabella di destinazione. In questo modo non devo avere un segnaposto per esso nell'istruzione Inserisci. Quindi una semplice selezione * nella tabella di destinazione ha popolato automaticamente questa colonna. Ecco le due istruzioni SQL che ho usato su PostgreSQL 9.6.4.

ALTER TABLE target ADD COLUMN some_column SERIAL;
INSERT INTO target SELECT * from source;
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.