INSERT
をネストすることはできません CASE
のステートメント 表現。私が見たものから派生して、この完全に異なるアプローチはそれを行う必要があります:
前提条件
-
実際には、外側の
SELECT
は必要ありません。 。 -
dm_name
/rm_name
dm
で一意に定義されています /rm
空ではありません(<> ''
)。CHECK
が必要です 確認するための制約。 -
両方の
d_id
の列のデフォルト およびr_id
z
で NULL(デフォルト)です。
dm_name
およびrm_name
相互に排他的
両方が同時に存在することがない場合。
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
d1
のすべての行を含む派生テーブルを生成します およびr1
他のそれぞれの列にNULLが追加されます(2つの間に重複はありません)。したがって、必要なINSERT
は1つだけです。 2つではなく。マイナーな最適化。
dm_name
およびrm_name
共存できる
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;
メモ
どちらも存在しない場合も、両方のバージョンが機能します。
INSERT
SELECT
の場合、何も挿入しません 行を返しません。
この操作と競合する可能性のある同時書き込みアクセスを処理する必要がある場合、同じトランザクションでこのステートメントを実行する前に、関連するテーブルをロックするのが簡単な解決策です。