危険察知4 択難易度 応用

状況

テストユーザー(メールが @test.example)の注文だけをキャンセル扱いにする。SQLite 3.33 以降の UPDATE ... FROM を使っている。

対象を正しく絞った UPDATE は?

UPDATE orders SET status = 'cancelled'FROM usersWHERE users.email LIKE '%@test.example';

正答

  1. UPDATE orders SET status = 'cancelled' FROM users WHERE orders.user_id = users.id AND users.email LIKE '%@test.example';
  2. UPDATE orders SET status = 'cancelled' FROM users WHERE users.email LIKE '%@test.example' AND orders.status = 'paid';
  3. UPDATE orders SET status = 'cancelled' FROM users WHERE orders.id = users.id AND users.email LIKE '%@test.example';
  4. 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

sqlupdatejoin

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

危険察知クイズへ