Làm cách nào để thêm khóa chính tăng tự động vào bảng hiện có, trong PostgreSQL?


Câu trả lời:


354

( Cập nhật - Cảm ơn những người đã bình luận )

Phiên bản hiện đại của PostgreSQL

Giả sử bạn có một bảng được đặt tên test1, mà bạn muốn thêm một cột tăng tự động, khóa chính id(thay thế). Lệnh sau phải đủ trong các phiên bản gần đây của PostgreSQL:

   ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

Các phiên bản cũ hơn của PostgreSQL

Trong các phiên bản cũ của PostgreSQL (trước 8.x?), Bạn phải làm tất cả công việc bẩn thỉu. Chuỗi lệnh sau nên thực hiện thủ thuật:

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

Một lần nữa, trong các phiên bản gần đây của Postgres, điều này gần tương đương với lệnh đơn ở trên.


3
Tôi đang sử dụng ORACLE, vì vậy việc chia sẻ nó có thể hữu ích cho những người ORACLE trong ORACLE: ALTER TABLE TEST1 ADD ID SỐ; CẬP NHẬT ID TEST1 = TEST1_SEQ.NEXTVAL; ALTER TABLE TEST1 THÊM KHÓA CHÍNH (ID); tạo một chuỗi TEST1_SEQ trước khi thực hiện câu lệnh CẬP NHẬT
msbyuva

Lưu ý rằng ADD PRIMARY KEYcũng tạo ra một NOT NULLràng buộc (được thử nghiệm trong postgres 9.3) như mong đợi và mong muốn.
Jared Beck

19
Trong Postgres, bạn hoàn toàn có thể sử dụng một lệnhALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;
resnyanskiy

1
Hơn nữa với nhận xét của @ resnyanskiy, điều này sẽ hoạt động ngay cả khi có dữ liệu trong bảng. ID được điền và không ràng buộc null được đặt. Toàn bộ câu trả lời có thể được thay thế bằng dòng trong nhận xét đó.
Synesso

1
@EricWang Cảm ơn, Eric, bạn nói đúng - Tôi tin rằng điều này đã không hoạt động một số phiên bản (năm) trước đây, nhưng tôi không chắc chắn. Biến câu trả lời thành cộng đồng-wiki.
leonbloy

57
ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

Đây là tất cả những gì bạn cần:

  1. Thêm idcột
  2. Dân trí nó với một chuỗi từ 1 đến đếm (*).
  3. Đặt nó làm khóa chính / không null.

Tín dụng được trao cho @resnyanskiy, người đã đưa ra câu trả lời này trong một bình luận.


2
Điều này nên được đánh dấu là câu trả lời và câu trả lời phải thuộc về @resnyanskiy
Eric Wang

Trước tiên tôi phải thả pkey và sau đó chạy nó. ALTER TABLE <table> DROP CONSTRAINT <pkey_name>;
Josh Robertson

10

Để sử dụng cột nhận dạng trong v10,

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

Để biết giải thích về các cột danh tính, hãy xem https://blog.2ndquadrant.com/postgresql-10-identity-columns/ .

Để biết sự khác biệt giữa TẠO B BYNG DEFAULT và LUÔN ĐƯỢC TẠO, hãy xem https://www.cybertec-postgresql.com/en/fterences-gains-and-pit thác / .

Để thay đổi trình tự, hãy xem https://popsql.io/learn-sql/postgresql/how-to-alter- resultence-in-postgresql / .


Vấn đề với giải pháp này là nếu bảng đã có hàng thì bạn gặp lỗi:SQL Error [23502]: ERROR: column "id" contains null values
isapir

3
@isapir: Có lỗi trong các phiên bản đầu (pg 10 và 10.1) tạo ra lỗi này. Nó đã được sửa với pg 10.2. Chi tiết tại đây: dba.stackexchange.com/q/200143/3684
Erwin Brandstetter

Cảm ơn @ erwin-brandstetter
isapir

Một năm sau tôi lại tìm thấy câu trả lời này, lỗi rõ ràng đã được sửa, được nâng cấp;)
isapir

2

Tôi đáp xuống đây vì tôi cũng đang tìm kiếm thứ gì đó tương tự. Trong trường hợp của tôi, tôi đã sao chép dữ liệu từ một tập hợp các bảng phân tầng có nhiều cột vào một bảng trong khi cũng gán các id hàng cho bảng đích. Đây là một biến thể của các phương pháp trên mà tôi đã sử dụng. Tôi đã thêm cột nối tiếp ở cuối bảng mục tiêu của mình. Theo cách đó, tôi không phải có một trình giữ chỗ cho nó trong câu lệnh Chèn. Sau đó, chọn đơn giản * vào bảng mục tiêu tự động điền vào cột này. Đây là hai câu lệnh SQL mà tôi đã sử dụng trên PostgreSQL 9.6.4.

ALTER TABLE target ADD COLUMN some_column SERIAL;
INSERT INTO target SELECT * from source;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.