危険察知4 択難易度 応用

状況

残すファイルの ID を keep_list に取り込み、それ以外を files から消す夜間バッチ。取り込みは別のスクリプトが行う。

このバッチで最も危ないのは?

-- 1. keep_list に残す file_id を取り込む(別スクリプト)-- 2. 残すもの以外を削除するDELETE FROM filesWHERE id NOT IN (SELECT file_id FROM keep_list);

正答

  1. keep_list.file_id に NULL が 1 つでもあると、files が全件消える
  2. 取り込みに失敗して keep_list が空だと、files が全件消える
  3. NOT IN は遅いので NOT EXISTS に書き換えるべき
  4. サブクエリに DISTINCT を付けないと、重複した ID でエラーになる

解説

NOT IN の右側が空集合のとき、条件はすべての行で真になる。取り込みスクリプトが失敗して keep_list が空のまま 2 が動くと、残すはずのファイルを含めて files が全件消える。前段の件数が 0 でなく想定範囲内であることを確かめてから削除する。逆に file_id に NULL があると NOT IN は真にならず何も消えないので、1 番目の「全件消える」は誤り。NOT EXISTS に替えても、空のときは同じく全件が対象になる。

参考: www.sqlite.org

sqlnot-indelete

この問題を含む 危険察知 のテストを制限時間つきで解く

危険察知クイズへ