テーブルを空にする - TRUNCATE
テーブルを高速に全削除する DDL 寄りの操作。DELETE との違いと MySQL の暗黙コミット
概念図
構文
sql
TRUNCATE TABLE table_name;サンプル
ステージングテーブルを高速に空にする
sql
TRUNCATE TABLE staging_orders;TRUNCATE とは
TRUNCATE TABLE はテーブルの全行を 高速に削除する文です。DELETE と違い行単位でログを書かず、内部的にはデータファイルを切り詰める(truncate)実装が多いため、数百万〜数億行でも一瞬で完了します。
多くの RDBMS で DDL 寄りの扱い(権限も通常は DROP に近い)で、トリガは発火しません。
DELETE との違い
- WHERE: TRUNCATE は全件のみ。条件指定不可
- 速度: TRUNCATE は行数に関わらずほぼ一定時間、DELETE は行数に比例
- トリガ: DELETE は発火、TRUNCATE は発火しない(PostgreSQL は TRUNCATE トリガを別途定義可)
- 自動採番のリセット: TRUNCATE は多くの RDBMS で AUTO_INCREMENT / SEQUENCE をリセット。DELETE はリセットしない
- 外部キー: TRUNCATE は参照されていると拒否される(PostgreSQL は
CASCADE指定で連鎖可)
sql
-- PostgreSQL: 関連テーブルも一緒に
TRUNCATE TABLE orders, order_items RESTART IDENTITY CASCADE;
-- SQL Server: FK 参照先は TRUNCATE 不可、DROP CONSTRAINT → TRUNCATE → 再作成が必要トランザクション挙動の RDBMS 差
- PostgreSQL: 完全にトランザクショナル。
BEGIN; TRUNCATE ...; ROLLBACK;で取り消せる - SQL Server: トランザクション内で使え、ROLLBACK 可能
- MySQL (InnoDB): 暗黙コミット。
TRUNCATEを実行した瞬間に現在のトランザクションがコミットされ、ROLLBACK できない - Oracle: DDL 扱いで暗黙コミット
- SQLite:
TRUNCATE文は持たず、DELETE FROM(WHERE なし)を内部的に TRUNCATE 最適化する
大事故: MySQL の暗黙コミット
MySQL で BEGIN; TRUNCATE TABLE users; と書いても、TRUNCATE の瞬間に暗黙コミットが発生し、以降の ROLLBACK は無効になります。これは初心者が最もハマる事故の一つです。
- 対策 1: MySQL で「取り消せる全件削除」が必要なら
DELETE FROM table;を使う(遅いがトランザクショナル) - 対策 2: どうしても TRUNCATE を使うなら、事前に
CREATE TABLE ... AS SELECTでバックアップを取る - 対策 3: 本番の TRUNCATE は必ず手順書レビュー・2 人確認を入れる
PostgreSQL / SQL Server はロールバック可能ですが、「どの RDBMS でも安全」と思い込まないことが肝心です。
sql
-- MySQL: これは取り消せない!
BEGIN;
TRUNCATE TABLE users; -- ここで暗黙 COMMIT
ROLLBACK; -- 無視される(users は空のまま)
-- PostgreSQL: これは取り消せる
BEGIN;
TRUNCATE TABLE users;
ROLLBACK; -- 元に戻る使いどころ
- ETL のステージングテーブルを毎回空にしてから再投入
- テスト・開発環境のデータリセット
- 監査ログの巨大テーブルをメンテナンス時間に一掃(PostgreSQL なら
RESTART IDENTITYも忘れずに)
本番のマスタテーブルや業務データには、誤操作耐性のため DELETE + WHERE を原則とし、TRUNCATE は「消えても再生成できる」テーブルに限定するのが安全です。
