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

状況

「企業 ID 42 の、plan が trial または expired のユーザを free に戻す」本番データ修正のダブルチェック中。company_id は整数列である。作業者が実行しようとしている SQL は次のとおり。

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

BEGIN;UPDATE users SET plan = 'free'WHERE company_id = 42 AND plan = 'trial' OR plan = 'expired';COMMIT;

正答

  1. AND が OR より先に評価され、他社の expired ユーザも更新される
  2. BEGIN から COMMIT までの間、他の利用者が users を読めなくなる
  3. SET で変更する plan を WHERE でも使うと、正しく絞り込めない
  4. company_id = 42 は '42' と引用符で囲まないと一致しない

解説

SQL では AND が OR より先に評価されるため、この WHERE は「(company_id = 42 AND plan = 'trial') OR plan = 'expired'」と解釈され、全企業の expired ユーザが更新される。正しくは「company_id = 42 AND plan IN ('trial', 'expired')」のように括弧や IN で範囲を閉じる。多くの DB ではトランザクション中でも他の利用者は読み取りでき、SET と WHERE で同じ列を使うことにも問題はない。整数列に 42 を書くのも正しい。

double-checkproductionsql

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

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