DELETEとTRUNCATE、どちらもテーブルを空にできる。違いは?
解説
TRUNCATE TABLE は、テーブル内の全行を一括で削除するDDL(データ定義言語)操作です。一方 DELETE FROM は行単位で削除するDML(データ操作言語)操作であり、トランザクション内で ROLLBACK によって取り消すことができます。TRUNCATEは多くのRDBMS(MySQL InnoDBは例外)でロールバックできません。これが最も重要な違いです。選択肢「違いはなく同じ動作」は誤りで、内部的な処理方式がまったく異なります。「DELETEのほうが高速」は逆で、TRUNCATEのほうが高速です。「TRUNCATEにWHERE句」も誤りで、TRUNCATEは条件指定できず常に全行削除です。DELETEが遅くてTRUNCATEが速い理由DELETEは1行ずつ削除処理を行い、各行の削除をトランザクションログに記録します。100万行あれば100万回の削除ログが書き込まれます。一方TRUNCATEはテーブルのデータページ自体を解放する方式で、行単位のログを残しません。大量データのテーブルを空にする場合、TRUNCATEはDELETEの数十倍〜数百倍速いこともあります。AUTO_INCREMENTのリセット有無実務で見落としがちな違いとして、TRUNCATEはAUTO_INCREMENT(連番)のカウンタをリセットする点があります。例えばIDが1000まで採番されたテーブルにTRUNCATEを実行すると、次のINSERTではID=1から始まります。DELETEで全行消した場合、カウンタはリセットされずID=1001から続きます。これは本番環境で「テストデータを消して入れ直したらIDが変わっていた」というトラブルの原因になることがあります。外部キーで他テーブルから参照されているIDがある場合、TRUNCATEによるリセットは整合性を壊す可能性があります。DDLとDMLの分類が実務に影響するケースTRUNCATEはDDL、DELETEはDMLという分類は単なる用語の問題ではありません。実務では以下のような影響があります。権限管理: TRUNCATEにはDROP権限が必要なDBMSが多く、DELETE権限だけでは実行できないトリガー: DELETEトリガーはDELETE時に発火するが、TRUNCATEでは発火しない。削除ログを別テーブルに書くトリガーを設定している場合、TRUNCATEで消すとログが残らない外部キー制約: 他テーブルから参照されているテーブルにはTRUNCATEを実行できないDBMSが多い。DELETEならCASCADE設定次第で可能MySQL InnoDBでのTRUNCATEとロールバックMySQLのInnoDBストレージエンジンでは、TRUNCATEもトランザクション内でロールバック可能な実装になっています。ただしこれはMySQL固有の挙動であり、PostgreSQL・Oracle・SQL ServerではTRUNCATEは暗黙的にCOMMITされ、ロールバックできません。DBMS間で挙動が異なるため、「TRUNCATEはロールバックできない」という理解をベースにしつつ、使用するDBMSのドキュメントを確認する習慣が重要です。現場での使い分け開発環境やテスト環境でテーブルを丸ごと空にしたい場合はTRUNCATEが適しています。高速で、カウンタもリセットされるため初期状態に戻しやすいからです。一方、本番環境で特定条件の行だけ消す場合や、トランザクションで安全に消したい場合はDELETEを使います。「全部消す=TRUNCATE」と機械的に判断せず、ロールバックの必要性・トリガーの有無・外部キー制約の3点を確認してから選ぶのが現場での判断基準です。