状況
テストユーザー(メールが @test.example)の注文だけをキャンセル扱いにする。SQLite 3.33 以降の UPDATE ... FROM を使っている。
対象を正しく絞った UPDATE は?
UPDATE orders SET status = 'cancelled'FROM usersWHERE users.email LIKE '%@test.example';正答
- UPDATE orders SET status = 'cancelled' FROM users WHERE orders.user_id = users.id AND users.email LIKE '%@test.example';
- UPDATE orders SET status = 'cancelled' FROM users WHERE users.email LIKE '%@test.example' AND orders.status = 'paid';
- UPDATE orders SET status = 'cancelled' FROM users WHERE orders.id = users.id AND users.email LIKE '%@test.example';
- UPDATE orders SET status = 'cancelled' FROM users WHERE orders.user_id = users.id OR users.email LIKE '%@test.example';
解説
元の SQL には orders と users を結び付ける条件がなく、テストユーザーが 1 人でもいれば orders の全行が更新される。orders.user_id = users.id で結合してから email で絞るのが正しい。orders.status = 'paid' を足しても全員の支払済み注文が対象になる。orders.id = users.id は注文番号とユーザー番号を比べる誤った結合で、たまたま一致した行が変わる。OR でつなぐと結合条件が意味を失う。MySQL の UPDATE ... JOIN でも同じ危険がある。
参考: www.sqlite.org
この問題を含む 危険察知 のテストを制限時間つきで解く
危険察知クイズへ