2012-02-01 32 views
10

Tôi đang chèn bản ghi số lượng lớn bằng cách sử dụng câu lệnh COPY trong PostgreSQL. Những gì tôi nhận ra là, các ID chuỗi không được cập nhật và khi tôi cố gắng chèn một bản ghi sau này, nó sẽ ném ID chuỗi trùng lặp. Tôi có nên cập nhật thủ công số thứ tự để nhận được số lượng bản ghi sau khi thực hiện COPY không? Không có giải pháp nào khi thực hiện COPY, chỉ cần tăng biến thứ tự, tức là trường khóa chính của bảng? Xin vui lòng làm rõ tôi về điều này. Cảm ơn trước!Tại sao các chuỗi không được cập nhật khi COPY được thực hiện trong PostgreSQL?

Ví dụ: nếu tôi chèn 200 bản ghi, COPY sẽ hoạt động tốt và bảng của tôi hiển thị tất cả các bản ghi. Khi tôi tự chèn một bản ghi sau, nó sẽ cho biết duplicate sequence ID error. Nó rất rõ ràng ngụ ý rằng nó không làm tăng các id trình tự trong COPY khi làm việc tốt trong quá trình INSERT bình thường. Thay vì chỉ dẫn id trình tự để đặt số lượng bản ghi tối đa, sẽ không có bất kỳ cơ chế nào để giáo dục lệnh COPY để tăng ID chuỗi trong tùy chọn COPYing hàng loạt?

Trả lời

3

Bạn có thể sao chép vào bảng chị em, sau đó insert into mytable select * from sister - điều đó sẽ tăng trình tự.

Nếu dữ liệu đã tải của bạn có trường id, không chọn nó cho chèn: insert into mytable (col1, col2, col3) select col1, col2, col3 from sister

+0

cảm ơn suy nghĩ của bạn ở đây! – siva

+0

+1 sẽ hoạt động – pilcrow

20

Bạn hỏi:

Tôi có nên tự cập nhật các số thứ tự để có được số lượng hồ sơ sau khi thực hiện COPY?

Có, bạn nên, như documented here:

Cập nhật giá trị chuỗi sau một COPY TỪ:

| BEGIN; 
| COPY distributors FROM 'input_file'; 
| SELECT setval('serial', max(id)) FROM distributors; 
| END; 

Bạn viết:

nó không tăng các id trình tự trong quá trình COPY là hoạt động tốt trong quá trình INSERTing bình thường

Nhưng điều đó không phải vậy! :) Khi bạn thực hiện một INSERT bình thường, thông thường bạn không chỉ định một giá trị rõ ràng cho khóa chính được hỗ trợ SEQUENCE. Nếu bạn đã làm, bạn sẽ chạy vào các vấn đề tương tự như bạn đang gặp bây giờ:

postgres=> create table uh_oh (id serial not null primary key, data char(1)); 
NOTICE: CREATE TABLE will create implicit sequence "uh_oh_id_seq" for serial column "uh_oh.id" 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "uh_oh_pkey" for table "uh_oh" 
CREATE TABLE 
postgres=> insert into uh_oh (id, data) values (1, 'x'); 
INSERT 0 1 
postgres=> insert into uh_oh (data) values ('a'); 
ERROR: duplicate key value violates unique constraint "uh_oh_pkey" 
DETAIL: Key (id)=(1) already exists. 

lệnh COPY của bạn, tất nhiên, được cung cấp một giá trị rõ ràng id, giống như ví dụ INSERT trên.

+0

Trình tự chỉ tăng khi giá trị được "tiêu thụ" từ nó để điền vào giá trị mặc định trong một INSERT (sử dụng nội bộ hàm nextval). Nếu bạn cung cấp các giá trị cho id của bạn, trình tự không được sử dụng, do đó nó không di chuyển. – peufeu

+0

@peufeu, vâng, đúng vậy – pilcrow

5

Tôi nhận thấy rằng điều này hơi cũ nhưng có thể ai đó vẫn có thể đang tìm câu trả lời. COPY hoạt động theo cách tương tự như INSERT, do đó, để chèn vào một bảng có một chuỗi, bạn chỉ đơn giản là không đề cập đến lĩnh vực trình tự ở tất cả và nó được đưa về chăm sóc cho bạn. Đối với COPY nó hoạt động theo cùng một cách chính xác. Nhưng nó không COPY yêu cầu tất cả các lĩnh vực trong bảng để có mặt trong tập tin văn bản? Câu trả lời đúng là KHÔNG, không, nhưng đó là hành vi mặc định.

để sao chép và rời khỏi chuỗi ra làm như sau:

COPY $YOURSCHEMA.$YOURTABLE(col1,col2,col3,col4) FROM '$your_input_file' DELIMITER ',' CSV HEADER; 

Không cần phải tự cập nhật các giản đồ sau đó, nó hoạt động như dự định và trong thử nghiệm của tôi chỉ là về càng nhanh.

+1

Chỉ cần thêm vào đây, tệp nguồn (đầu vào) chỉ cần có các cột bạn đang sao chép trong đó. Postgres không phải là "thông minh" - nó không nhìn vào các tiêu đề cột để phù hợp với các cột bạn đã đặt tên trong lệnh sao chép. Vì vậy, trong ví dụ @Phobos ở trên, tệp đầu vào phải chỉ có 4 cột. Chỉ hy vọng sẽ cứu ai đó một số rắc rối - câu trả lời này đã giúp tôi. –

Các vấn đề liên quan