Jak dodać automatycznie zwiększający klucz podstawowy do istniejącej tabeli w PostgreSQL?

190

Mam tabelę z istniejącymi danymi. Czy istnieje sposób na dodanie klucza podstawowego bez usuwania i ponownego tworzenia tabeli?

xRobot
źródło

Odpowiedzi:

355

( Zaktualizowano - Dzięki osobom, które skomentowały )

Nowoczesne wersje PostgreSQL

Załóżmy, że masz tabelę o nazwie test1, do której chcesz dodać idkolumnę z automatycznym zwiększaniem, kluczem podstawowym (zastępczym). W najnowszych wersjach PostgreSQL powinno wystarczyć następujące polecenie:

   ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

Starsze wersje PostgreSQL

W starych wersjach PostgreSQL (przed wersją 8.x?) Trzeba było wykonać całą brudną robotę. Następująca sekwencja poleceń powinna załatwić sprawę:

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

Ponownie, w ostatnich wersjach Postgres jest to mniej więcej odpowiednik pojedynczego polecenia powyżej.

leonbloy
źródło
3
Używam ORACLE, więc udostępnianie może być przydatne dla facetów ORACLE W ORACLE: ALTER TABLE TEST1 ADD ID NUMBER; UPDATE TEST1 SET ID = TEST1_SEQ.NEXTVAL; ZMIEŃ TABELĘ TEST 1 DODAJ KLUCZ PODSTAWOWY (ID); utwórz sekwencję TEST1_SEQ przed wykonaniem instrukcji UPDATE
msbyuva
Zauważ, że ADD PRIMARY KEYtworzy również NOT NULLograniczenie (testowane w Postgresie 9.3) zgodnie z oczekiwaniami i oczekiwaniami.
Jared Beck
19
W Postgres można w ogóle używać jednego poleceniaALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;
resnyanskiy
1
W nawiązaniu do komentarza @ resnyanskiy zadziała to nawet wtedy, gdy w tabeli są dane. Identyfikatory są zapełniane i nie jest ustawione ograniczenie zerowe. Całą odpowiedź można zastąpić wierszem w tym komentarzu.
Synesso
1
@EricWang Dzięki, Eric, masz rację - uważam, że to nie działało w niektórych wersjach (lata) temu, ale nie jestem pewien. Zamieniłem odpowiedź w wiki-społeczność.
leonbloy
57
ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

To wszystko, czego potrzebujesz:

  1. Dodaj idkolumnę
  2. Wypełnij sekwencją od 1 do zliczenia (*).
  3. Ustaw go jako klucz podstawowy / nie zerowy.

Podziękowania należą się @resnyanskiy, który udzielił odpowiedzi w komentarzu.

Synesso
źródło
2
To powinno być oznaczone jako odpowiedź, a odpowiedź powinna należeć do @resnyanskiy
Eric Wang
Musiałem najpierw upuścić klucz, a następnie uruchomić go. ALTER TABLE <table> DROP CONSTRAINT <pkey_name>;
Josh Robertson
10

Aby użyć kolumny tożsamości w wersji 10,

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

Aby uzyskać wyjaśnienie kolumn tożsamości, zobacz https://blog.2ndquadrant.com/postgresql-10-identity-columns/ .

Różnicę między WYTWORZONYM PRZEZ DOMYŚLNĄ a ZAWSZE WYTWORZONĄ, patrz https://www.cybertec-postgresql.com/en/sequences-gains-and-pitfalls/ .

Aby zmienić sekwencję, patrz https://popsql.io/learn-sql/postgresql/how-to-alter-sequence-in-postgresql/ .

jhoanna
źródło
Problem z tym rozwiązaniem polega na tym, że jeśli tabela zawiera już wiersze, SQL Error [23502]: ERROR: column "id" contains null values
pojawia
3
@isapir: Wystąpił błąd we wczesnych wersjach (str. 10 i 10.1) powodujący ten błąd. Zostało to naprawione za pomocą str. 10.2. Szczegóły tutaj: dba.stackexchange.com/q/200143/3684
Erwin Brandstetter
Dzięki @ erwin-brandstetter
isapir
Rok później znalazłem tę odpowiedź ponownie, błąd najwyraźniej naprawiony, przegłosowano;)
isapir
2

Wylądowałem tutaj, bo też szukałem czegoś takiego. W moim przypadku kopiowałem dane z zestawu tabel pomostowych z wieloma kolumnami do jednej tabeli, jednocześnie przypisując identyfikatory wierszy do tabeli docelowej. Oto wariant powyższych podejść, których użyłem. Dodałem kolumnę szeregową na końcu mojej tabeli docelowej. W ten sposób nie muszę mieć symbolu zastępczego w instrukcji Insert. Następnie prosty wybór * w tabeli docelowej automatycznie wypełnił tę kolumnę. Oto dwie instrukcje SQL, których użyłem w PostgreSQL 9.6.4.

ALTER TABLE target ADD COLUMN some_column SERIAL;
INSERT INTO target SELECT * from source;
Dean Sha
źródło