Query Go
テーブルを空にする - TRUNCATE の使い方・オプション・サンプル

テーブルを空にする - TRUNCATE

テーブルを高速に全削除する DDL 寄りの操作。DELETE との違いと MySQL の暗黙コミット

概念図

TRUNCATE diagram

構文

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 は「消えても再生成できる」テーブルに限定するのが安全です。

関連トピック