TRUNCATE と DROP

TRUNCATE と DROP とは

TRUNCATE文とDROP文の違いと、それぞれの使い方をSQLで学びます。本レッスンでは、TRUNCATE と DROP の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

なぜ重要か

「テーブルを綺麗に空にしたい」「テーブルそのものを消したい」というニーズに応える 2 つの命令が TRUNCATEDROP です。両方とも DELETE と似た見た目で破壊力は段違いに大きく、本番で間違えるとバックアップが無ければ即終了級の事故になります。一方で、テスト用 DB のデータを毎日リセットする、もう使わない一時テーブルを掃除するなど、開発現場では日常的に使う命令でもあります。本レッスンでは「3 つの削除命令」 (DELETE / TRUNCATE / DROP) の差分を整理して、いつ何を使えばよいかを判断できるようにします。

3 つの削除命令を比較

diagram (will load when visible)

構文と挙動

SQL クエリ

-- 1. DELETE: 行を 1 件ずつ消す (WHERE が必須レベル) DELETE FROM logs WHERE created_at < '2024-01-01'; -- 2. TRUNCATE: 全行を一気に消す。採番値もリセットされる場合がある TRUNCATE TABLE logs; -- 3. DROP TABLE: テーブルそのものを消す DROP TABLE logs;

TRUNCATE の特徴

  • 全行削除専用、WHERE は付けられない
  • DELETE よりはるかに高速 (ログを 1 行ずつ取らない、内部実装はテーブル再作成に近い)
  • 採番値の扱いはDBMSやオプションで異なる
  • 多くの場合トランザクション内でロールバックできない
  • 外部キーで参照されているテーブルでは失敗することがある

DROP の特徴

  • テーブル定義そのものを消す。SELECT も INSERT もできなくなる
  • 復活させたければ CREATE TABLE をもう一度実行 (中身は空)
  • 本番では「使ってないテーブルを掃除する」前にレビューと別名リネーム → しばらく様子を見る、という運用が安全

いつどれを使うか

ニーズ推奨
ユーザが退会した行を消すDELETE (条件付き)
古いログを 30 日分削除DELETE LIMIT で少しずつ
テストデータを毎日リセットTRUNCATE
もう使わない一時テーブルDROP TABLE
マイグレーション失敗で残ったテーブルDROP TABLE IF EXISTS

SQL クエリ

-- 冪等に DROP したい場合 DROP TABLE IF EXISTS tmp_import;

注意 本番で TRUNCATE / DROP を打つときは「もう一度バックアップ取った?」と必ず自問する。DELETE はトランザクションで救えますが、TRUNCATE と DROP はほとんどの場合で救えません。

テスト DB を毎晩クリーンにする CI で TRUNCATE TABLE users; TRUNCATE TABLE orders; ... を流す書き方は実務でよくあります。シードスクリプトも「TRUNCATE → INSERT」のセットで冪等性を担保します。

DROP より一段安全なテクニックとして「まずリネーム」があります。RENAME TABLE old_name TO _zzz_old_name; でテーブル名を変えて、しばらく様子を見て、参照ゼロを確認できたら DROP TABLE _zzz_old_name; を流す、という運用です。リネーム直後はテーブル自体は残っているので、いざとなれば元の名前に戻せます。

マイグレーションの「ロールバックの戻し方」

本番でテーブルを消す系のマイグレーションを流すときは、いざ問題が起きた時に「どう戻すか」を事前に書いて手元に置いてから実行します。たとえば DROP するなら、その前に取った mysqldump の出力をすぐに mysql < dump.sql で流せる状態にしておきます。「戻し方が決まっていないマイグレーションは流さない」を鉄則にすると、夜中の事故電話が減ります。

TRUNCATE と外部キー

TRUNCATE は他テーブルから外部キーで参照されているテーブルに対しては失敗することがあります。

SQL クエリ

-- orders.user_id が users.id を参照している場合 TRUNCATE TABLE users; -- → エラー

本番では「参照しているテーブルから順に消す」「FOREIGN_KEY_CHECKS を一時的に外す」などの工夫が必要です。次の章で外部キーの仕組みを学ぶと、なぜこの制限があるのかが腑に落ちます。

まとめ

  • DELETE は条件付き、TRUNCATE は全行リセット、DROP はテーブルごと消す
  • 速度は DELETE < TRUNCATE、戻せるのは DELETE のみ
  • DROP TABLE IF EXISTS は冪等な DDL に必須
  • RENAME TABLE で「DROP より一段安全な掃除」ができる
  • 本番では実行前に「バックアップとロールバック手順」を必ず用意する

次のレッスン

次は DDL / DML 実践クイズ です。DDL(データ定義言語)とDML(データ操作言語)の理解度をクイズで確認しましょう。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. TRUNCATE/DROP の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. TRUNCATE/DROP とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

テーブル構造

schema.sql

CREATE TABLE tmp_import ( id INT PRIMARY KEY, payload VARCHAR(100) NOT NULL ); INSERT INTO tmp_import (id, payload) VALUES (1, 'old-1'), (2, 'old-2'), (3, 'old-3'); CREATE TABLE archive_log ( id INT PRIMARY KEY, message VARCHAR(100) NOT NULL ); INSERT INTO archive_log (id, message) VALUES (1, 'kept');

期待される出力

table_name
archive_log

ヒント

query.sql
query.sql
学習モード
コードの実行結果
データベースを初期化中...