はじめに
あるアプリの開発中にやってしまった失敗の話です。
別システムから取得したデータをOracleのテーブルにインサートするプログラムにバグがあり、まったく同じ内容のレコードが複数回インサートされてしましました。(このテーブルにはプライマリーキーがないため全てのカラムが同じ内容のレコードが存在し得ます)
テーブルにはすでに過去のデータが入っているため全件削除してインサートし直すことは出来ず、そもそもプログラム実行日時が入るカラムがあるのでインサートの再実行はやりたくありません。
どうしても重複したレコードだけを削除する必要がありました。
ネット上にはWHERE句で結合して削除するやり方が見つかったんですが、カラム数がかなり多いためJOINして削除する方法を考えました。
考え方
- 全レコードを全てのカラムでグループ化してレコード固有のROWIDの最小値の一覧を取得します
- この一覧に無いROWIDのレコードを削除することでユニークな行だけが残ります。
コード
DELETE FROM
table_a T1
WHERE
T1.ROWID IN (
SELECT
T2.ROWID
FROM
table_a T2
LEFT JOIN (
SELECT
MIN(ROWID) RID
FROM
table_a
GROUP BY
column_1,
column_2,
column_3,
(以下カラムが続く)
) T3 ON T2.ROWID = T3.RID
WHERE
T3.RID IS NULL
)