PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Điều gì xảy ra với các bản sao khi chèn nhiều hàng?

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?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Gấu trúc ghi khung dữ liệu vào lược đồ postgresql khác

  2. Sửa lỗi “INSERT có nhiều biểu thức hơn cột mục tiêu” trong PostgreSQL

  3. bộ chuyển đổi postgres rails có hỗ trợ ssl không?

  4. Kiểm tra xem giá trị có tồn tại trong mảng Postgres không

  5. Nhiều kết nối cơ sở dữ liệu trong Rails