2016-04-22 24 views
12

cú pháp chính xác của upsert với postgresql 9.5, bên dưới truy vấn cho thấy lỗi column reference "gallery_id" is ambiguous, tại sao?Làm thế nào để thực hiện chính xác upsert trong postgres 9.5

var dbQuery = `INSERT INTO category_gallery (
    category_id, gallery_id, create_date, create_by_user_id 
) VALUES ($1, $2, $3, $4) 
    ON CONFLICT (category_id) 
    DO UPDATE SET 
    category_id = $1, 
    last_modified_date = $3, 
    last_modified_by_user_id = $4 
    WHERE gallery_id = $2`; 

tôi đã cố gắng thay đổi WHERE gallery_id = $2;-WHERE category_gallery.gallery_id = $2; sau đó cho thấy lỗi there is no unique or exclusion constraint matching the ON CONFLICT specification, nhưng Tôi không muốn thiết lập gallery_id hoặc category_id như là duy nhất bởi vì tôi muốn chắc chắn rằng cả hai cột là như nhau thì làm cập nhật ....

Làm thế nào để thực hiện đúng upsert trong postgres 9.5?

nếu ON CONFLICT cần cột duy nhất, tôi có nên sử dụng phương pháp khác không?



Tôi muốn chắc chắn nhiều cột cả hai mâu thuẫn thì đừng cập nhật, sử dụng đúng là những gì

var dbQuery = `INSERT INTO category_gallery (
    category_id, gallery_id, create_date, create_by_user_id 
) VALUES ($1, $2, $3, $4) 
    ON CONFLICT (category_id, gallery_id) 
    DO UPDATE SET 
    category_id = $1, 
    last_modified_date = $3, 
    last_modified_by_user_id = $4 
    WHERE gallery_id = $2`; 


var dbQuery = `INSERT INTO category_gallery (
    category_id, gallery_id, create_date, create_by_user_id 
) VALUES ($1, $2, $3, $4) 
    ON CONFLICT (category_id AND gallery_id) 
    DO UPDATE SET 
    category_id = $1, 
    last_modified_date = $3, 
    last_modified_by_user_id = $4 
    WHERE gallery_id = $2`; 

bảng (category_id, gallery_id không cột độc đáo)

category_id | gallery_id | create_date | create_by_user_id | last_modified_date | last_modified_by_user_id 
1 | 1 | ... 
1 | 2 | ... 
2 | 2 | ... 
1 | 3 | ... 

Trả lời

28

Các Cấu trúc ON CONFLICT yêu cầu ràng buộc UNIQUE để hoạt động. Từ các tài liệu trên INSERT .. ON CONFLICT clause:

Các ON CONFLICT khoản tùy chọn xác định một hành động thay thế cho việc nâng cao một sự vi phạm độc đáo hoặc trừ chế lỗi vi phạm. Đối với mỗi hàng riêng lẻ được đề xuất để chèn, chèn chèn sẽ tiến hành hoặc, nếu một ràng buộc hoặc chỉ mục được chỉ định bởi xung đột_target bị vi phạm, thì xung đột thay thế được thực hiện. ON CONFLICT DO NOTHING chỉ đơn giản là tránh chèn một hàng làm hành động thay thế của nó. ON CONFLICT DO UPDATE cập nhật hàng hiện có xung đột với hàng được đề xuất để chèn làm hành động thay thế của nó.

Bây giờ, câu hỏi không rõ ràng nhưng bạn có thể cần một ràng buộc UNIQUE trên 2 cột kết hợp: (category_id, gallery_id).

ALTER TABLE category_gallery 
    ADD CONSTRAINT category_gallery_uq 
    UNIQUE (category_id, gallery_id) ; 

Nếu hàng được chèn phù hợp cả giá trị với một hàng đã có trên bảng, sau đó thay vì INSERT, làm một UPDATE:

INSERT INTO category_gallery (
    category_id, gallery_id, create_date, create_by_user_id 
) VALUES ($1, $2, $3, $4) 
    ON CONFLICT (category_id, gallery_id) 
    DO UPDATE SET 
    last_modified_date = EXCLUDED.create_date, 
    last_modified_by_user_id = EXCLUDED.create_by_user_id ; 

Bạn có thể sử dụng các cột của Ràng buộc UNIQUE:

ON CONFLICT (category_id, gallery_id) 

hoặc tên ràng buộc:

ON CONFLICT ON CONSTRAINT category_gallery_uq 
+0

cảm ơn trả lời nhưng tôi không muốn category_id hoặc gallery_id là cột duy nhất, đề cập đến được đề cập. Tôi muốn chắc chắn nếu category_id và gallery_id cả hai cùng tạo một hàng mới, vui lòng xem ví dụ về ngày cập nhật của tôi trong câu hỏi – user1575921

+0

wow, cảm ơn! Tôi hiểu lầm, tôi sẽ thử nó ngay bây giờ – user1575921

+0

nếu đã tồn tại 'category_id = 1 và gallery_id = 3' sau đó cập nhật, không chèn. Tôi sử dụng kịch bản của bạn, nếu tôi muốn cập nhật 'category_id = 2, nơi gallery_id = 3' không hoạt động. hay tôi nên thêm một tập lệnh cập nhật khác? – user1575921

1

Như như thay thế đơn giản hóa để the currently accepted answer, các UNIQUE hạn chế có thể được ẩn danh thêm khi tạo của bảng:

CREATE TABLE table_name (
    id TEXT PRIMARY KEY, 
    col TEXT, 
    UNIQUE (id, col) 
); 

Sau đó, truy vấn upsert trở thành (tương tự như những gì đã được trả lời):

INSERT INTO table_name (id, col) VALUES ($1, $2) 
ON CONFLICT (id, col) 
    DO UPDATE SET col = $2; 
Các vấn đề liên quan