実務シチュエーション4 択難易度 応用

状況

キャンセル済み注文の明細を削除する本番作業。orders の主キーは id で、order_id という列はない。order_items には order_id 列がある。作業者の SQL は次のとおり。

この SQL で最も危ない点は?

DELETE FROM order_itemsWHERE order_id IN (  SELECT order_id FROM orders WHERE status = 'canceled');

正答

  1. サブクエリの中では WHERE を使えないため、構文エラーで止まる
  2. orders に order_id がなく外側の列と解釈され、全明細が消えうる
  3. IN ではなく EXISTS を使わないと、削除が非常に遅くなる
  4. 外部キーがあると DELETE は必ず失敗するため、影響は出ない

解説

サブクエリの中で orders に存在しない order_id を書くと、多くの DB はエラーにせず、外側の order_items.order_id を参照したと解釈する。その結果、キャンセル済み注文が 1 件でもあれば条件はほぼ全行で真になり、明細がまとめて消える。正しくは SELECT id とする。実行前に同じ条件の SELECT で件数を確かめれば気づける。EXISTS との速度差は二次的な論点で、サブクエリでの WHERE は正しい構文である。

double-checkproductionsql

この問題を含む 実務シチュエーション のテストを制限時間つきで解く

実務シチュエーションクイズへ