topic: db (PDO / SQL / マルチDB) / ch08 — トランザクション / 演習 02
📝 ドリル 02 — エラーで rollBack
問題
accounts テーブルに 2 件 INSERT しようとして、2 件目で意図的に失敗 させ、
rollBack で全部巻き戻したい。最後に SELECT したとき何も追加されていないことを示す。
INSERT 内容:
- 1 件目:
id = 10, balance = 1000→ 成功するはず - 2 件目:
id = 10, balance = 2000→ PK 重複 で例外発生
try ... catch (PDOException $e) で例外を捕まえて rollBack を呼び、
そのとき "rollback" と出力してください。
その後、SELECT で残った行を id 昇順で "{id}: {balance}" 形式で出す。
初期データは空。 rollBack されたので 1 件目も取り消され、SELECT は 0 件。
期待される出力:
rollback
採点
php scripts/grade.php topics/11-db/ch08-transactions/drill/02-rollback-on-error/
ヒント
$pdo->beginTransaction();で開始try { ... $pdo->commit(); } catch (PDOException $e) { $pdo->rollBack(); echo "rollback\n"; }- 2 件目の INSERT で同じ
id = 10を入れれば PK 重複で例外 - catch を抜けた後に SELECT で残りを foreach 出力 (0 件なので何も出ない)
テストケース
期待される出力
rollback
📄 starter.php(雛形)
このコードから書き始めてください。
<?php
$pdo = new PDO('sqlite:' . getenv('DOJO_DB_PATH'));
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// TODO: beginTransaction でトランザクションを開始する
// TODO: try で 2 回 INSERT する (2 回目は id=10 を重複させて例外を起こす)
// 成功したら commit、失敗したら catch で rollBack + "rollback" を出力する
// TODO: SELECT で残った行を id 昇順で "{id}: {balance}" で出力する (0 件のはず)
✅ 解答例を見る(自分で解いてから)
<?php
$pdo = new PDO('sqlite:' . getenv('DOJO_DB_PATH'));
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->beginTransaction();
try {
$pdo->exec("INSERT INTO accounts (id, balance) VALUES (10, 1000)");
$pdo->exec("INSERT INTO accounts (id, balance) VALUES (10, 2000)"); // PK 重複でエラー
$pdo->commit();
echo "commit\n";
} catch (PDOException $e) {
$pdo->rollBack();
echo "rollback\n";
}
foreach ($pdo->query("SELECT id, balance FROM accounts ORDER BY id") as $row) {
echo "{$row['id']}: {$row['balance']}\n";
}