Cột nhận dạng PostgreQuery 10 nhận được giá trị null null khi chèn nhiều hàng với từ khóa mặc định


7

Gần đây tôi đã nâng cấp từ PostgreQuery 9.5 lên PostgreSQL 10. Một trong những tính năng tiện lợi trong PostgreQuery 10 là loại cột nhận dạng mới , thay thế cho loại giả nối tiếp của PostgreQuery. Tài liệu chính thức cho cột danh tính có thể được tìm thấy trên một CREATE TABLEtrang.

Tuy nhiên, khi chèn nhiều hàng vào một bảng có GENERATED BY DEFAULT AS IDENTITYcột sử dụng từ khóa DEFAULTđể lấy giá trị ID tiếp theo, giá trị mặc định sẽ trở lại là null.

Ví dụ: giả sử tôi có một bảng

CREATE TABLE test (
  id int GENERATED BY DEFAULT AS IDENTITY,
  t text
);
CREATE TABLE

Chèn một hàng với DEFAULTtừ khóa dường như hoạt động tốt.

INSERT INTO test (id, t) VALUES (DEFAULT, 'a');
INSERT 0 1

Chèn nhiều hàng thì không.

INSERT INTO test (id, t) VALUES (DEFAULT, 'b'), (DEFAULT, 'c');
ERROR:  null value in column "id" violates not-null constraint
DETAIL:  Failing row contains (null, b).

Chèn nhiều hàng bằng cách sử dụng mặc định ngầm cũng hoạt động.

INSERT INTO test (t) VALUES ('d'), ('e');
INSERT 0 2

Vấn đề được chỉ định ở trên dường như không xuất hiện khi sử dụng kiểu SERIALgiả cột.

CREATE TABLE test2 (
  id SERIAL,
  t text
);
CREATE TABLE

INSERT INTO test2 (id, t) VALUES (DEFAULT, 'a'), (DEFAULT, 'b');
INSERT 0 2

Vì vậy, câu hỏi của tôi là: tôi có thiếu một cái gì đó? Là DEFAULTtừ khóa không mong đợi để làm việc với cột nhận dạng mới ? Hay đây là một lỗi?

Câu trả lời:


4

Đây thực tế là một lỗi. Tôi đã xác minh nó. Tôi đã đi để xem nếu nó đã được nộp và có vẻ như nó đã được. Nó không chỉ nộp, cam kết là có.

Bạn có thể xem thử nghiệm của họ, giống hệt như thử nghiệm của bạn

+-- VALUES RTEs
+INSERT INTO itest3 VALUES (DEFAULT, 'a');
+INSERT INTO itest3 VALUES (DEFAULT, 'b'), (DEFAULT, 'c');
+SELECT * FROM itest3;

Vì vậy, hãy chờ đợi, nó đã có cho PostgreQuery 10.2.

Có thể giải quyết xung quanh cho PostgreSQL <10.2

Nếu bạn hoàn toàn phải có điều này, và sử dụng cột ẩn không được chấp nhận. Một giải pháp dễ dàng là truy xuất chuỗi với chức năng thông tin danh mục

pg_get_serial_sequence(table_name, column_name) 

Mà tôi tin rằng nên hoạt động và để đặt nó làm mặc định.

ALTER TABLE ONLY test
  ALTER COLUMN id
  DEFAULT nextval('seqname');

2
Cảm ơn bạn đã kiểm tra rằng nó đã được nộp (và đã cam kết). Kế hoạch của tôi là tiếp tục sử dụng các trình tự khi cần thiết cho đến 10.2
danwoz

4

Đó là một lỗi như @Evan đã phát hiện ra, vì vậy cho đến khi nó được sửa, chúng ta phải xử lý nó.

Như bạn có thể biết, thật dễ dàng để xử lý trường hợp chèn nhiều cột trong đó không phải tất cả các giá trị default- chỉ cần bỏ qua (các) cột mà bạn muốn defaultgiá trị được chèn hoàn toàn, defaultlà mặc định :

INSERT INTO test (t) VALUES ('b'), ('c');
SELECT * FROM test;
id | t
-: | : -
 1 | b
 2 | c

dbfiddle ở đây

Nếu có nhiều cột và bạn muốn tất cả chúng được mặc định, bạn vẫn có thể sử dụng CTE :

WITH w AS (INSERT INTO test (t) VALUES (DEFAULT) RETURNING t )
INSERT INTO test (t) SELECT w.t FROM w CROSS JOIN generate_series(1, 1);
SELECT * FROM test;
id | t  
-: | : -
 1 | foo
 2 | foo

dbfiddle ở đây

Thật không may, không có cách giải quyết dễ dàng nếu bạn cần tất cả các cột được điền với default:

Đối với trường hợp khi chỉ có một cột và đó là một chuỗi, tôi thấy không có cách nào để sử dụng mặc định.

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.