sql >> データベース >  >> RDS >> PostgreSQL

データ変更CTEのINSERTステートメントとCASE式の組み合わせ

    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の場合、何も挿入しません 行を返しません。

    この操作と競合する可能性のある同時書き込みアクセスを処理する必要がある場合、同じトランザクションでこのステートメントを実行する前に、関連するテーブルをロックするのが簡単な解決策です。




    1. SQLServerでデータファイルとログファイルのデフォルトのファイルの場所を見つける方法

    2. MariaDBにテーブルが存在するかどうかを確認する4つの方法

    3. 非推奨の機能がSQLServerインスタンスでまだ使用されているかどうかを確認する2つの方法

    4. 時間間のデータベース内の同時イベントの検索