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

外部キーの依存関係を持つ重複行を削除するにはどうすればよいですか?

    単一のSQLステートメントを使用すると、これをはるかに効率的に行うことができます。 データ変更CTE

    WITH plan AS (
       SELECT *
       FROM  (
          SELECT recid, min(recid) OVER (PARTITION BY cdesc) AS master_recid
          FROM   cpt
          ) sub
       WHERE  recid <> master_recid  -- ... <> self
       )
     , upd_lab AS (
       UPDATE lab l
       SET    cpt_recid = p.master_recid   -- link to master recid ...
       FROM   plan p
       WHERE  l.cpt_recid = p.recid
       )
    DELETE FROM cpt c
    USING  plan p
    WHERE  c.recid = p.recid
    RETURNING c.recid;
    

    db <> fiddle こちら (11ページ)
    SQL Fiddle (9.6ページ)

    これは多くである必要があります より速く、よりクリーンに。ループは比較的高価であり、例外処理は比較的さらに高価です。
    さらに重要なのは、labでの参照です。 cptのそれぞれのマスター行にリダイレクトされます 自動的に、これは元のコードにはまだ含まれていませんでした。したがって、すべての重複を一度に削除できます

    必要に応じて、これをplpgsqlまたはSQL関数でラップすることもできます。

    説明

    1. 最初のCTEでplan 、同じcdescを使用して各パーティションのマスター行を識別します 。あなたの場合、最小のrecidを持つ行 。

    2. 2番目のCTEでupd_lab 重複を参照するすべての行をcptのマスター行にリダイレクトします 。

    3. 最後に、重複を削除します。これにより、依存する行が残りのマスター行に実質的に同時にリンクされるため、例外が発生することはありません。

    ON DELETE RESTRICT

    すべてのCTEとステートメントのメインクエリ 基になるテーブルの同じスナップショットを実質的に同時に操作します 。基になるテーブルに対する互いの影響はわかりません:

    ON DELETE RESTRICTを使用したFK制約が予想される場合があります 例外を発生させる理由は、[ドキュメントごと] [3]:

    ただし、上記のステートメントは単一のコマンドです そして、[再びマニュアル] [3]:

    大胆な強調鉱山。制限の少ないデフォルトのON DELETE NO ACTIONで機能します もちろんです。

    ただし、同じテーブルへの同時トランザクションの書き込みには注意してください。ただし、これは一般的な考慮事項であり、このタスクに固有のものではありません。

    UNIQUEには例外が適用されます およびPRIMARY KEY 制約がありますが、これは関係ありません ケース:



    1. ORACLE-LOOP(またはSIMILAR)内で具体的な結果を見つける

    2. リストビューでのページネーション

    3. OracleストアドプロシージャのWHERE句にコンマ区切り値で送信する

    4. SQLServerでEXISTS論理演算子を使用する方法-SQLServer/TSQLチュートリアルパート125