INSERT
sẽ chỉ chèn tất cả các hàng và không có gì đặc biệt sẽ xảy ra, trừ khi bạn có một số loại ràng buộc không cho phép các giá trị trùng lặp / chồng chéo (PRIMARY KEY
, UNIQUE
, CHECK
hoặc EXCLUDE
ràng buộc) - mà bạn không đề cập đến trong câu hỏi của mình. Nhưng đó là điều bạn có thể đang lo lắng.
Giả sử một UNIQUE
hoặc ràng buộc PK trên (col1,col2)
, bạn đang xử lý một cuốn sách giáo khoa UPSERT
tình huống. Nhiều câu hỏi và câu trả lời liên quan để tìm ở đây.
Nói chung, nếu bất kỳ ràng buộc bị vi phạm, một ngoại lệ được đưa ra (trừ khi bị mắc kẹt trong giao dịch con giống như nó có thể xảy ra trong ngôn ngữ phía máy chủ thủ tục như plpgsql) sẽ quay lại không chỉ câu lệnh mà còn cả toàn bộ giao dịch .
Không ghi đồng thời
Tức là:Không có giao dịch nào khác sẽ cố gắng ghi vào cùng một bảng tại cùng một thời điểm.
-
Loại trừ các hàng đã có trong bảng với
WHERE NOT EXISTS ...
hoặc bất kỳ kỹ thuật áp dụng nào khác: -
Chọn các hàng không có trong bảng khác
-
Và đừng quên xóa các bản sao trong tập hợp được chèn cũng sẽ không bị loại trừ bởi bán chống tham gia
WHERE NOT EXISTS ...
Một kỹ thuật để giải quyết cả hai cùng một lúc sẽ là EXCEPT
:
INSERT INTO tbl (col1, col2)
VALUES
(text 'v1', text 'v2') -- explicit type cast may be needed in 1st row
, ('v3', 'v4')
, ('v3', 'v4') -- beware of dupes in source
EXCEPT SELECT col1, col2 FROM tbl;
EXCEPT
không có từ khóa ALL
gấp các hàng trùng lặp trong nguồn. Nếu bạn biết không có bản sao hoặc bạn không muốn gấp các bản sao một cách âm thầm, hãy sử dụng EXCEPT ALL
(hoặc một trong các kỹ thuật khác). Xem:
- Sử dụng mệnh đề EXCEPT trong PostgreSQL
Nói chung, nếu bảng mục tiêu là lớn , WHERE NOT EXISTS
kết hợp với DISTINCT
trên nguồn có thể sẽ nhanh hơn:
INSERT INTO tbl (col1, col2)
SELECT *
FROM (
SELECT DISTINCT *
FROM (
VALUES
(text 'v1', text'v2')
, ('v3', 'v4')
, ('v3', 'v4') -- dupes in source
) t(c1, c2)
) t
WHERE NOT EXISTS (
SELECT FROM tbl
WHERE col1 = t.c1 AND col2 = t.c2
);
Nếu có thể có nhiều bản lừa đảo, bạn phải trả gấp chúng trong nguồn trước. Nếu không, hãy sử dụng ít hơn một truy vấn con.
Có liên quan:
- Chọn các hàng không có trong bảng khác
Với ghi đồng thời
Sử dụng Postgres UPSERT
triển khai INSERT ... ON CONFLICT ...
trong Postgres 9.5 trở lên:
INSERT INTO tbl (col1,col2)
SELECT DISTINCT * -- still can't insert the same row more than once
FROM (
VALUES
(text 'v1', text 'v2')
, ('v3','v4')
, ('v3','v4') -- you still need to fold dupes in source!
) t(c1, c2)
ON CONFLICT DO NOTHING; -- ignores rows with *any* conflict!
Đọc thêm:
- Cách sử dụng RETURNING với ON CONFLICT trong PostgreSQL?
- Làm cách nào để chèn một hàng chứa khóa ngoại?
Tài liệu:
- Hướng dẫn sử dụng
- Trang cam kết
- Trang Wiki của Postgres
Câu trả lời tham khảo của Craig cho UPSERT
vấn đề:
- Làm cách nào để UPSERT (MERGE, INSERT ... ON DUPLICATE UPDATE) trong PostgreSQL?