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

Trả lại id nếu một hàng tồn tại, INSERT nếu không

Một giải pháp trong một câu lệnh SQL duy nhất. Yêu cầu PostgreSQL 8.4 hoặc mới hơn.
Hãy xem xét bản trình diễn sau:

Thiết lập thử nghiệm:

CREATE TEMP TABLE tbl (
  id  serial PRIMARY KEY
 ,txt text   UNIQUE   -- obviously there is unique column (or set of columns)
);

INSERT INTO tbl(txt) VALUES ('one'), ('two');

Lệnh INSERT / SELECT:

WITH v AS (SELECT 'three'::text AS txt)
    ,s AS (SELECT id FROM tbl JOIN v USING (txt))
    ,i AS (
       INSERT INTO tbl (txt)
       SELECT txt
       FROM   v
       WHERE  NOT EXISTS (SELECT * FROM s)
       RETURNING id
       )
SELECT id, 'i'::text AS src FROM i
UNION  ALL
SELECT id, 's' FROM s;
  • CTE v đầu tiên không hoàn toàn cần thiết, nhưng đạt được rằng bạn phải nhập giá trị của mình chỉ một lần.

  • CTE thứ hai được chọn id từ tbl nếu "hàng" tồn tại.

  • CTE thứ ba mà tôi chèn "hàng" thành tbl nếu (và chỉ khi) nó không tồn tại, trả về id .

  • SELECT cuối cùng trả về id . Tôi đã thêm một cột src cho biết "nguồn" - liệu "hàng" đã tồn tại trước hay chưa và id đến từ một CHỌN hoặc "hàng" mới và id cũng vậy .

  • Phiên bản này phải nhanh nhất có thể vì nó không cần thêm SELECT từ tbl và sử dụng CTE thay thế.

Để làm cho điều này an toàn trước các điều kiện chạy đua có thể xảy ra trong môi trường nhiều người dùng:
Cũng để biết các kỹ thuật được cập nhật bằng cách sử dụng UPSERT mới trong Postgres 9.5 trở lên:

  • CHỌN hoặc CHÈN trong một hàm có nguy cơ gặp phải các điều kiện về chủng tộc không?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Đơn giản hóa trường hợp lồng nhau khi câu lệnh

  2. Cần tìm gì nếu Bản sao PostgreSQL của bạn đang bị trễ

  3. Postgres lỗi cú pháp bảng thả

  4. Sử dụng bảng SAO CHÉP nhị phân FROM với psycopg2

  5. Chọn ba giá trị hàng đầu trong mỗi nhóm