Làm cách nào tôi có thể thêm một cột vào cơ sở dữ liệu Postgresql không cho phép null?


243

Tôi đang thêm một cột "KHÔNG NULL" mới vào cơ sở dữ liệu Postgresql của mình bằng truy vấn sau (được khử trùng cho Internet):

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) NOT NULL;

Mỗi lần tôi chạy truy vấn này, tôi nhận được thông báo lỗi sau:

ERROR:  column "mycolumn" contains null values

Tôi bối rối. Tôi làm sai ở đâu?

LƯU Ý: Tôi đang sử dụng pgAdmin III (1.8.4) là chủ yếu, nhưng tôi đã gặp lỗi tương tự khi tôi chạy SQL từ bên trong Terminal.

Câu trả lời:


400

Bạn phải đặt một giá trị mặc định.

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) NOT NULL DEFAULT 'foo';

... some work (set real values as you want)...

ALTER TABLE mytable ALTER COLUMN mycolumn DROP DEFAULT;

1
Giải pháp tốt đẹp. Tôi không thể truy cập tài liệu postgres trực tuyến vì một số lý do để xem cú pháp sẽ là gì cho việc này.
Sean Bright

4
@SeanBright, bạn có thể truy cập vào postgres doc ngoại tuyến bằng cách thực hiện man ALTER_TABLE :)
allan.simon

@ allan.simon Tôi chưa bao giờ sử dụng PostgreSQL trước đây và tôi không cài đặt nó ở bất cứ đâu.
Sean Sáng

2
Để làm rõ: giá trị mặc định chỉ cần để cập nhật các hàng hiện có, đó là lý do tại sao nó có thể bị loại bỏ ngay sau đó. Tất cả các hàng hiện có đã được cập nhật khi bảng bị thay đổi (có thể mất một thời gian, rõ ràng)
MSalters

2
Điều này sẽ không hoạt động nếu bạn muốn sử dụng một cột khác để tính giá trị ban đầu cho các hàng hiện có. Câu trả lời của j_random_hacker cho phép điều đó, làm cho nó mạnh mẽ hơn.
jpmc26

82

Như những người khác đã quan sát, bạn phải tạo một cột không thể hoặc cung cấp giá trị DEFAULT. Nếu điều đó không đủ linh hoạt (ví dụ: nếu bạn cần tính toán giá trị mới cho từng hàng riêng lẻ), bạn có thể sử dụng thực tế là trong PostgreQuery, tất cả các lệnh DDL có thể được thực thi trong một giao dịch:

BEGIN;
ALTER TABLE mytable ADD COLUMN mycolumn character varying(50);
UPDATE mytable SET mycolumn = timeofday();    -- Just a silly example
ALTER TABLE mytable ALTER COLUMN mycolumn SET NOT NULL;
COMMIT;

7
ngay cả trong một giao dịch, KHÔNG NULL được thực thi ngay lập tức, vì vậy trước tiên phải thêm cột, điền giá trị, sau đó thêm KHÔNG NULL - như câu trả lời này. (đã thử nghiệm trên postgres 9.6)
Beni Cherniavsky-Paskin

48

Vì các hàng đã tồn tại trong bảng, ALTERcâu lệnh đang cố gắng chèn NULLvào cột vừa tạo cho tất cả các hàng hiện có. Bạn sẽ phải thêm cột dưới dạng cho phép NULL, sau đó điền vào cột với các giá trị bạn muốn và sau đó đặt cột thành NOT NULLsau đó.


7
Ví dụ về cách làm nó sẽ thực sự tốt đẹp. Mặt khác, giải pháp của Luc dường như hoàn thiện hơn và sẵn sàng để sử dụng.
Victor Farazdagi

5

Bạn cần xác định mặc định hoặc thực hiện những gì Sean nói và thêm nó mà không bị ràng buộc null cho đến khi bạn điền nó vào các hàng hiện có.


2

Chỉ định một giá trị mặc định cũng sẽ hoạt động, giả sử giá trị mặc định là phù hợp.


2
Nó sẽ cải thiện câu trả lời để đưa ra cú pháp sửa đổi để tạo cột có giá trị mặc định (để minh họa).
hardmath

1

Hoặc, tạo một bảng mới dưới dạng tạm thời với cột bổ sung, sao chép dữ liệu sang bảng mới này trong khi thao tác nó khi cần thiết để điền vào cột mới không thể rỗng, sau đó trao đổi bảng thông qua thay đổi tên hai bước.

Vâng, nó phức tạp hơn, nhưng bạn có thể cần phải làm theo cách này nếu bạn không muốn CẬP NHẬT lớn trên bàn trực tiếp.


3
Tôi đã không -1 bạn, nhưng tôi nghĩ có thể có những khó khăn tinh tế với điều này - ví dụ: tôi cá rằng các chỉ số, trình kích hoạt và lượt xem hiện tại sẽ tiếp tục đề cập đến bảng gốc ngay cả sau khi đổi tên khi tôi nghĩ họ lưu trữ dựa vào bảng (không thay đổi) thay vì tên của nó.
j_random_hacker

1
Có, tôi đã phải tuyên bố rằng bảng mới phải là một bản sao chính xác của bản gốc, bao gồm thêm các chỉ số và như vậy. Xấu của tôi vì quá ngắn gọn Lý do cho điều này là cũng có những khác biệt tinh tế khi thực hiện ALTER trên bàn có thể tồn tại và đôi khi bạn cần phải tạo ra nó.
alphadogg

Ví dụ: sử dụng phương pháp DEFAULT, bạn sẽ thêm giá trị mặc định đó vào mỗi hàng. Không chắc chắn làm thế nào Postgres khóa một bảng khi làm điều này. Hoặc, nếu thứ tự cột quan trọng, bạn không thể thêm một cột bằng lệnh ALTER.
alphadogg

Đủ công bằng, ALTER TABLE không khóa bảng theo tài liệu PostgreSQL, tuy nhiên cách tiếp cận phi giao dịch của bạn có nguy cơ mất các thay đổi nếu bảng thực sự tồn tại. Ngoài ra, tôi đề nghị rằng bất kỳ mã nào dựa trên thứ tự cột bị hỏng (tất nhiên có thể nằm ngoài tầm kiểm soát của bạn).
j_random_hacker

2
Cách tiếp cận này cũng đặc biệt có vấn đề nếu bảng được tham chiếu bởi các chỉ mục khóa ngoài vì tất cả chúng cũng phải được tạo lại.
Aryeh Leib Taurog

0

truy vấn này sẽ tự động cập nhật null

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) DEFAULT 'whatever' NOT NULL;

-6

Điều này làm việc cho tôi: :)

ALTER TABLE your_table_name ADD COLUMN new_column_name int;

2
Không có NOT NULLràng buộc về truy vấn của bạn. Tất nhiên là nó hoạt động.
Sylvain
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.