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 trongdm
/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_id
vàr_id
trongz
là NULL (mặc định).
dm_name
và rm_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ừ d1
và r1
đượ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_name
và rm_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.