topic: db (PDO / SQL / マルチDB) / ch11 — MySQL 固有の文法と運用 / 演習 03
📝 ドリル 03 — TRUNCATE と DELETE の挙動を比較する
問題
採点ランナーが items テーブルに 3 件のレコードを用意する。
SELECT COUNT(*) FROM itemsで件数を取得し、before: {N}を出力- 全件削除する
- MySQL なら
TRUNCATE TABLE items - SQLite / PostgreSQL は
DELETE FROM items(SQLite に TRUNCATE は無い・PostgreSQL は TRUNCATE もあるが ここでは DELETE で統一)
- MySQL なら
- 削除後にもう一度
SELECT COUNT(*) FROM itemsで件数を取り、after delete: {N}を出力
期待される出力
before: 3
after delete: 0
ヒント
scripts/shared/db-connect.phpのdojo_db_connect()を使う- 件数取得は
(int) $pdo->query("SELECT COUNT(*) FROM items")->fetchColumn()で 1 行 - driver は
getenv('DOJO_DB_DRIVER') ?: 'sqlite' - 文字列なので
before: 3の:の後ろにスペース 1 つ・改行で終わる点に注意
採点
php scripts/grade.php topics/11-db/ch11-mysql-specific/drill/03-truncate-vs-delete/
採点ランナーは driver に応じて setup.sql / setup.mysql.sql / setup.pgsql.sql を使い分け、items テーブルに 3 件入った状態から採点を始める。
学ぶこと (本質)
TRUNCATEは DDL 扱い — 速いが ROLLBACK できないDELETE FROMは DML 扱い — トランザクションで取り消せる- 件数だけ見ると差は出ないが、直後の INSERT で振られる ID に差が出る:
- TRUNCATE 後: 1 から振り直し
- DELETE 後: 続きから (例: 元が 1,2,3 なら次は 4)
- 本番のデータは原則
DELETE FROM ... WHERE ...。TRUNCATEは テスト DB のリセット で使う
テストケース
期待される出力
before: 3
after delete: 0
📄 starter.php(雛形)
このコードから書き始めてください。
<?php
require __DIR__ . '/../../../../../scripts/shared/db-connect.php';
$pdo = dojo_db_connect();
$driver = getenv('DOJO_DB_DRIVER') ?: 'sqlite';
// TODO:
// 1) SELECT COUNT(*) FROM items で件数を取り、"before: {N}" を出力
// 2) driver が 'mysql' なら TRUNCATE TABLE items、それ以外 (sqlite / pgsql) は DELETE FROM items を実行
// 3) もう一度 COUNT(*) を取り、"after delete: {N}" を出力
//
// 期待される出力:
// before: 3
// after delete: 0
✅ 解答例を見る(自分で解いてから)
<?php
require __DIR__ . '/../../../../../scripts/shared/db-connect.php';
$pdo = dojo_db_connect();
$driver = getenv('DOJO_DB_DRIVER') ?: 'sqlite';
$before = (int) $pdo->query("SELECT COUNT(*) FROM items")->fetchColumn();
echo "before: {$before}\n";
if ($driver === 'mysql') {
$pdo->exec("TRUNCATE TABLE items");
} else {
$pdo->exec("DELETE FROM items");
}
$after = (int) $pdo->query("SELECT COUNT(*) FROM items")->fetchColumn();
echo "after delete: {$after}\n";