状況
残すファイルの ID を keep_list に取り込み、それ以外を files から消す夜間バッチ。取り込みは別のスクリプトが行う。
このバッチで最も危ないのは?
-- 1. keep_list に残す file_id を取り込む(別スクリプト)-- 2. 残すもの以外を削除するDELETE FROM filesWHERE id NOT IN (SELECT file_id FROM keep_list);正答
- keep_list.file_id に NULL が 1 つでもあると、files が全件消える
- 取り込みに失敗して keep_list が空だと、files が全件消える
- NOT IN は遅いので NOT EXISTS に書き換えるべき
- サブクエリに DISTINCT を付けないと、重複した ID でエラーになる
解説
NOT IN の右側が空集合のとき、条件はすべての行で真になる。取り込みスクリプトが失敗して keep_list が空のまま 2 が動くと、残すはずのファイルを含めて files が全件消える。前段の件数が 0 でなく想定範囲内であることを確かめてから削除する。逆に file_id に NULL があると NOT IN は真にならず何も消えないので、1 番目の「全件消える」は誤り。NOT EXISTS に替えても、空のときは同じく全件が対象になる。
参考: www.sqlite.org
この問題を含む 危険察知 のテストを制限時間つきで解く
危険察知クイズへ