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

Kết hợp các câu lệnh INSERT trong một CTE sửa đổi dữ liệu với một biểu thức CASE

Bạn không thể lồng INSERT câu lệnh trong CASE biểu hiện. Xuất phát từ những gì tôi thấy, cách tiếp cận hoàn toàn khác này sẽ làm được điều đó:

Giả định

  • Bạn không thực sự cần SELECT bên ngoài .

  • dm_name / rm_name được định nghĩa duy nhất trong dm / rm và không trống (<> '' ). Bạn phải có CHECK ràng buộc để đảm bảo.

  • Cột mặc định cho cả d_idr_id trong z là NULL (mặc định).

dm_namerm_name loại trừ lẫn nhau

Nếu cả hai không bao giờ xuất hiện cùng một lúc.

WITH d1 AS (
   INSERT INTO d (dm_id)
   SELECT dm.dm_id 
   FROM   import
   JOIN   dm USING (dm_name)
   RETURNING d_id
   )
, r1 AS (
   INSERT INTO r (rm_id)
   SELECT rm.rm_id 
   FROM   import
   JOIN   rm USING (rm_name)
   RETURNING r_id
   )
, z1 AS (
   INSERT INTO z (d_id, r_id)
   SELECT d_id, r_id
   FROM d1 FULL JOIN r1 ON FALSE
   RETURNING z_id
   )
INSERT INTO port (z_id)
SELECT z_id
FROM   z1;

FULL JOIN .. ON FALSE tạo một bảng dẫn xuất với tất cả các hàng từ d1r1 được nối với NULL cho cột khác tương ứng (không có chồng chéo giữa hai cột). Vì vậy, chúng tôi chỉ cần một INSERT thay vì hai. Tối ưu hóa nhỏ.

dm_namerm_name có thể cùng tồn tại

WITH i AS (
   SELECT dm.dm_id, rm.rm_id
   FROM   import
   LEFT   JOIN dm USING (dm_name)
   LEFT   JOIN rm USING (rm_name)
   )
, d1 AS (
   INSERT INTO d (dm_id)
   SELECT dm_id FROM i WHERE dm_id IS NOT NULL
   RETURNING dm_id, d_id
   )
, r1 AS (
   INSERT INTO r (rm_id)
   SELECT rm_id FROM i WHERE rm_id IS NOT NULL
   RETURNING rm_id, r_id
   )
, z1 AS (
   INSERT INTO z (d_id, r_id)
   SELECT d1.d_id, r1.r_id
   FROM   i
   LEFT   JOIN d1 USING (dm_id)
   LEFT   JOIN r1 USING (rm_id)
   WHERE  d1.dm_id IS NOT NULL OR
          r1.rm_id IS NOT NULL
   RETURNING z_id
   )
INSERT INTO port (z_id)
SELECT z_id FROM z1;

Ghi chú

Cả hai phiên bản đều hoạt động nếu cả hai phiên bản đều không tồn tại.

INSERT không chèn gì nếu SELECT không trả về (các) hàng.

Nếu bạn phải đối phó với quyền truy cập ghi đồng thời có thể xung đột với thao tác này, cách khắc phục nhanh sẽ là khóa các bảng có liên quan trước khi bạn chạy câu lệnh này trong cùng một giao dịch.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Trường mô hình duy nhất trong Django và phân biệt chữ hoa chữ thường (postgres)

  2. PostgreSQL:Chọn dữ liệu có tương tự trên trường dấu thời gian

  3. Mục tiêu thời gian khôi phục Pgbackrest

  4. Bảng chữ cái với một số lượng lớn hoặc không xác định các danh mục

  5. Cách make_interval () hoạt động trong PostgreSQL