EXISTS句を使用して特定の条件のレコードを削除する方法

表題の通りです。 条件としては下記のような感じ

  • TableAに存在せず、TableBには存在するレコードをTableCから削除する
  • それぞれのテーブルには同じキー'X'が存在しており、必ず一意となる

結論

まず結論から。下記のような感じでいけました。 EXISTS句は2箇所使用しました。

DELETE 
FROM
  TableC tC 
WHERE
  EXISTS ( 
    SELECT
      1 
    FROM
      TableB tB 
    WHERE
      tC.X = tB.X 
      AND tB.X IN ( 
        SELECT
          tB.X 
        FROM
          TableB tB 
        WHERE
          NOT EXISTS ( 
            SELECT
              1 
            FROM
              TableA tA 
            WHERE
              tB.X = tA.X 
          ) 
      )
  ); 

解説

内側のSELECT文から何をしているのか説明します

一番内側のNOT EXISTSの部分

この部分です。

SELECT
 tB.X 
FROM
 TableB tB 
WHERE
 NOT EXISTS ( 
  SELECT
   1 
  FROM
   TableA tA 
  WHERE
   tB.X = tA.X 
 ) 

ここではまずTableAに存在せず、TableBに存在するキーXを取り出します。

次にEXISTS句の部分

次は下記の部分です。

FROM
 TableC tC 
WHERE
 EXISTS ( 
  SELECT
   1 
  FROM
   TableB tB 
  WHERE
   tC.X = tB.X 
   AND tB.X IN ( 
    SELECT
     tB.X 
    FROM
     TableB tB 
    WHERE
     NOT EXISTS ( 
      SELECT
       1 
      FROM
       TableA tA 
      WHERE
       tB.X = tA.X 
     ) 
   )

このほうがわかりやすいかと思ったのでFROM句から記載しています。 ここでは一番内側のSELECT文で取り出した「TableAに存在せず、TableBに存在するキーX」と 削除対象のテーブルであるTableCのキーXを紐付けることで 「TableAに存在せず、TableBに存在するキーXに紐付く削除対象TableCのレコード」を取り出しています。

DELETE

最後にこれをDELETEすることで「TableAに存在せず、TableBには存在するレコードをTableCから削除する」を実現しました。 ちなみに、なぜTableAとCを比較して削除しなかったかというと TableBとCは親子関係になっており、TableBには存在していることを確認したかったからです。

最後に

私自身の理解力も乏しいので、上手く言葉として言い表せませんでした。 絶賛ORACLE勉強中なので、また理解が進んで良い方法がわかれば訂正・追記したいと思います。