Як додати первинний ключ з автоматичним збільшенням до існуючої таблиці в PostgreSQL?


190

У мене є таблиця з існуючими даними. Чи є спосіб додати первинний ключ без видалення та повторного створення таблиці?

Відповіді:


355

( Оновлено - Дякую людям, які коментували )

Сучасні версії PostgreSQL

Припустимо, у вас є таблиця з назвою test1, до якої ви хочете додати idстовпчик автоматичного збільшення, первинного ключа (сурогат). У останніх версіях PostgreSQL наступної команди має бути достатньо:

   ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

Старіші версії PostgreSQL

У старих версіях PostgreSQL (до 8.x?) Вам довелося виконати всю брудну роботу. Наступна послідовність команд повинна зробити фокус:

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

Знову ж таки, в останніх версіях Postgres це приблизно еквівалентно єдиній команді вище.


3
Я використовую ORACLE, тому обмін може бути корисним для хлопців ORACLE В ORACLE: ALTER TABLE TEST1 ADD ID NO; UPDATE TEST1 SET ID = TEST1_SEQ.NEXTVAL; АЛЬТЕР ТАБЛИЧНИЙ ТЕСТ1 ДОДАТИ ПЕРШИЙ КЛЮЧ (ID); створити послідовність TEST1_SEQ перед виконанням оператора UPDATE
msbyuva

Зауважимо, що ADD PRIMARY KEYтакож створюється NOT NULLобмеження (тестоване в постгресах 9.3), як очікувалося і потрібно.
Джаред Бек

19
У Postgres ви можете взагалі використовувати одну командуALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;
resnyanskiy

1
На додаток до коментаря @ resnyanskiy, це працюватиме навіть тоді, коли в таблиці є дані. Ідентифікатори заповнюються і не встановлюється нульове обмеження. Вся відповідь може бути замінена рядком у цьому коментарі.
Синесо

1
@EricWang Спасибі, Еріку, ти маєш рацію - я вважаю, що деякі версії (років) тому не працювали, але я не впевнений. Відповідь перетворили на спільноту-вікі.
leonbloy

57
ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

Це все, що вам потрібно:

  1. Додайте idстовпчик
  2. Зарахуйте його послідовністю від 1 до підрахунку (*).
  3. Встановити його як основний ключ / не нульовий.

Подяка @resnyanskiy, який дав цю відповідь у коментарі.


2
Це слід позначити як відповідь, а відповідь має належати @resnyanskiy
Ерік Ван

Мені довелося спочатку скинути pkey, а потім запустити цю. ALTER TABLE <table> DROP CONSTRAINT <pkey_name>;
Джош Робертсон

10

Щоб використовувати стовпчик ідентифікації в v10,

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

Для пояснення стовпців ідентифікацій див. Https://blog.2ndquadrant.com/postgresql-10-identity-column/ .

Про різницю між ЗАГАЛЕНОЮ ЗАВДАННЯМИ ТА ЗАГАЛЬНЕНОЮ ЗАВЖДИ, див. Https://www.cybertec-postgresql.com/en/sequences-gains-and-pitfalls/ .

Про зміну послідовності див. Https://popsql.io/learn-sql/postgresql/how-to-alter-sequence-in-postgresql/ .


Проблема цього рішення полягає в тому, що якщо таблиця вже містить рядки, ви отримуєте помилку:SQL Error [23502]: ERROR: column "id" contains null values
isapir

3
@isapir: У ранніх версіях (pg 10 та 10.1) виникла помилка, яка спричинила цю помилку. Це було зафіксовано за допомогою pg 10.2. Деталі тут: dba.stackexchange.com/q/200143/3684
Erwin Brandstetter

Дякуємо @ erwin-marketetter
isapir

Через рік я знову знайшов цю відповідь, помилка, мабуть, виправлена, анульована;)
isapir

2

Я приземлився тут, бо шукав щось подібне теж. У моєму випадку я копіював дані з набору послідовних таблиць з багатьма стовпцями в одну таблицю, а також присвоював ідентифікатори рядків цільовій таблиці. Ось варіант вищезазначених підходів, якими я користувався. Я додав послідовний стовпчик в кінці своєї цільової таблиці. Таким чином, я не повинен мати його заповнювача у виписці Insert. Потім простий вибір * в цільову таблицю автоматично заповнив цей стовпець. Ось два оператори SQL, які я використовував у PostgreSQL 9.6.4.

ALTER TABLE target ADD COLUMN some_column SERIAL;
INSERT INTO target SELECT * from source;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.