対象と位置付け:このページはOracle Database 19c配下の通常永続表を中心に、MySQL 8.4 InnoDB・PostgreSQL 18・SQL Server Database Engineを比較します。表の一部パーティションや一時表、クラスタ、参照パーティション表等の制限は個別確認が必要です。「DDLだから全DBでROLLBACK不可」「空の子表なら親を消せる」という製品横断の説明はできません。
表関連の一覧から操作を選び、DDLのCOMMIT境界とROLLBACKの取消範囲を合わせて確認してください。
図はOracle 19c通常表・MySQL 8.4 InnoDBで別の子表から有効なFKがあり、検査有効・CASCADEなしの関係を示す模式図です。全製品の挙動や実端末での実測を表す図ではありません。自己参照や製品固有のCASCADE等の例外は本文で区別します。
| この記事の要点 |
|
TRUNCATE TABLE とは
TRUNCATE TABLE は、表に入っているデータをすべて削除し、表の構造(カラム定義・インデックス・制約)はそのまま残す SQL です。「中身を空にして作り直したい」ときに使います。
旧基本形を保持しています。Oracle 19cはTABLEが必要ですが、PostgreSQL 18とMySQL 8.4はTABLEを省略できます。旧コメントのPostgreSQLを含む説明をそのまま採用しないでください。実在usersへの実行案内ではありません。
-- 基本形
TRUNCATE TABLE users;
-- Oracle / PostgreSQL では TABLE を省略できない DB もあるが
-- MySQL は TABLE を省略しても動く
TRUNCATE users;
DELETE / TRUNCATE / DROP の違い
この 3 つは「消す」という点では同じですが、何が残るかと取り消せるかが違います。ここを取り違えると本番でデータを失います。
| 観点 | DELETE | TRUNCATE | DROP |
|---|---|---|---|
| 分類 | DML | DDL | DDL |
| 表の定義 | 残る | 残る | 消える |
| データ | 条件に合う行 | 全行 | 全行 |
| WHERE で絞る | できる | できない | できない |
| ROLLBACK | transaction対応エンジンで未COMMITなら可能。MySQL InnoDB等 | MySQL 8.4・Oracle 19c通常永続表は不可。PostgreSQL 18・SQL Server Database Engineはtransaction内で可能 | 製品・オブジェクト・transaction条件による。DDLという分類だけでは決められない |
| 速度 | 条件・索引・ログ・参照・ロック待ちによる | 全行DELETEより効率的なことがあるが、無停止・一定時間は保証しない | 依存関係やロック等による。用途の異なる操作の速度だけで選ばない |
| トリガ | 対象のDELETEトリガがあれば発火条件に従う | ON DELETEは発火しない。PostgreSQLはON TRUNCATE、OracleはTRUNCATEを対象にしたschema/databaseのDDLトリガを別に確認 | DELETEトリガとは別。Oracle等のDDLトリガの対象になり得る |
| AUTO_INCREMENT | MySQLの通常DELETEでカウンタ初期化を期待しない | MySQLは開始値へ。SQL Server identityは定義したseedへ。PostgreSQLは既定CONTINUE IDENTITY。全製品で1ではない | 表の列は消えるが、独立sequenceの一律削除・初期化を意味しない |
使い分けではまず対象と取消条件を確認します。一部の行を対象にするならDELETE、表定義も不要ならDROPが候補です。全行を消して同じ表を使う場合でも、TRUNCATEの参照制約・採番・トリガ・COMMIT境界を満たすか先に判断します。テストデータや中間表でも、利用者のいない専用表であることと復旧手順を確認し、全削除の用途だけでTRUNCATEを自動選択しません。
ROLLBACK で戻せない
この節の「戻せない」はMySQL 8.4とOracle Database 19cの通常永続表を対象にします。DDLのatomicity(途中障害時に全体を完了または取消する性質)と、成功後に利用者がROLLBACKできることは別です。Oracleでは構文として有効な通常DDLの実行前にCOMMITがあり、DDLが失敗しても先行DMLまで戻るとは限りません。Oracle 19c COMMITの仕様を参照してください。private temporary table(PTT)のTRUNCATEはexisting transactionをCOMMITしない例外です。この非COMMIT例外を、PTTの消した行をROLLBACKで復元できるという意味に読み替えません。
旧MySQL / Oracle混在コメントを保持していますが、このSTART TRANSACTIONはMySQL用でありOracleの構文ではありません。MySQL InnoDBの専用表・FK等の制限を満たす例に限り、DELETEは未COMMITなら取消可能です。TRUNCATEは先行DMLもCOMMITし得ます。Oracle通常永続表の説明とは分けて読んでください。
-- MySQL / Oracle: これは戻せない
START TRANSACTION;
TRUNCATE TABLE users; -- ここで暗黙コミットが走る
ROLLBACK; -- 効かない。users は空のまま
-- DELETE なら戻せる
START TRANSACTION;
DELETE FROM users;
ROLLBACK; -- 元に戻る
| DBMS | トランザクション内での TRUNCATE |
|---|---|
| MySQL | 8.4の通常表では暗黙COMMIT。InnoDBのatomic DDL対応でも、成功したTRUNCATEを利用者のROLLBACKで戻せない。先行する別表DMLの確定にも注意 |
| Oracle | 19cの通常永続表はROLLBACK不可。TRUNCATE後のFLASHBACK TABLEでも内容を戻せない。PTTはexisting transactionをCOMMITしない例外で、通常永続表と混同しない |
| SQL Server | Database Engineでは明示transaction内・COMMIT前ならROLLBACK可能。Azure Synapse Analyticsではtransaction内でTRUNCATEを実行できず、この比較を一律転用できない |
| PostgreSQL | 18はtransaction内でROLLBACK可能。ACCESS EXCLUSIVEロックを取り、同時アクセスを遮る。transaction-safeとMVCC-safeは別 |
MySQLとOracleの通常永続表では、事前に復元可能な退避と復旧手順を用意し、別作業の未確定更新がないことを確認します。PostgreSQL 18やSQL Server Database Engineでも、既にCOMMITした処理を後続ROLLBACKで戻すことはできません。バックアップの存在だけで対象・時点・復元権限・所要時間の確認が済むわけではありません。
外部キーがあると失敗する
Oracle 19cの通常永続表で、別の子表から有効な外部キーにより参照される親表は、通常のTRUNCATEを拒否されます。MySQL 8.4 InnoDBでもFOREIGN_KEY_CHECKSが有効な同種の参照があると拒否されます。これは子行の有無ではなく制約定義の問題で、子表が空でも同じです。自己参照等の製品固有の例外と区別してください。子表を先にTRUNCATEすると、親は拒否されたまま子データだけが失われ得ます。
旧MySQLのERROR 1701表示例を保持しています。これは全DB共通のエラー番号ではありません。子行が0件でもFK定義が残ることが原因になり、子表のTRUNCATEは解決になりません。
ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint
(MySQL の例)
次の3案は同等の安全な解決策ではありません。参照構造と消す範囲を読取りで確認し、必要な変更は別途レビューします。
| 方法 | 内容 | 注意 |
|---|---|---|
| 子から先に消す | 子表をTRUNCATEしても親を参照するFK定義は残る | Oracle 19c通常表・MySQL 8.4 InnoDBでは親の拒否を回避できない。子行だけ失うおそれがあり、安全策として推奨しない |
| DELETE を使う | 条件・対象件数・参照動作を確認してからtransaction内で検討 | RESTRICT/NO ACTIONなら拒否され得る。ON DELETE CASCADEなら子行も削除され得る。トリガ・権限・ロックにも従うため「確実」とは言えない |
| 制約を一時無効化 | エラーを通すために検査や制約を解除する案は採用しない | MySQLでFOREIGN_KEY_CHECKSを1へ戻しても、無効期間の既存行は自動再検査されない。設定復帰と参照整合性の確認は別 |
PostgreSQL 18は既定RESTRICTで、参照元を同じTRUNCATE文の対象に含めない場合は拒否します。CASCADEは依存先を再帰的に対象へ加えるため、自動的な回避策にしません。Oracle 19cのTRUNCATE CASCADEも有効なON DELETE CASCADE制約を介して子・孫表を対象にする製品固有の機能です。DELETE時の参照動作とTRUNCATEのCASCADE指定は別です。SQL Server Database Engineは別表からFK参照される表を拒否し、自己参照には例外があります。
まず次のMySQL 8.4向け読取専用SQLで、選択中のDATABASEにあるusersを参照先にするFK列を調べます。TABLE_SCHEMAは子表側、REFERENCED_TABLE_SCHEMAは親表側なので取り違えません。複合FKは列ごとに1行表示し、制約名・列順も照合します。DATABASE()がNULL(未選択)の場合や、権限によりメタデータが見えない場合は0件になり得ます。0件≠安全で、表の実在・権限・同時DDLや別製品の制約まで保証するSQLではありません。
-- MySQL 8.4: read only. First confirm the selected database is not NULL.
SELECT DATABASE() AS selected_database;
SELECT TABLE_SCHEMA AS child_schema,
TABLE_NAME AS child_table,
CONSTRAINT_NAME,
ORDINAL_POSITION,
COLUMN_NAME AS child_column,
REFERENCED_TABLE_SCHEMA AS parent_schema,
REFERENCED_TABLE_NAME AS parent_table,
REFERENCED_COLUMN_NAME AS parent_column
FROM information_schema.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_SCHEMA = DATABASE()
AND REFERENCED_TABLE_NAME = 'users'
ORDER BY TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME, ORDINAL_POSITION;
限定runtime検証:2026-10-27に、ローカルMySQL 8.4.13で新しい合成parents/children等のInnoDB検体を検証しました。外部キーはON DELETE/ON UPDATE RESTRICT、FOREIGN_KEY_CHECKSは有効のままです。子行がある初期状態から子表TRUNCATE後0件を別接続で確認し、空の子表でも親TRUNCATEは実際にERROR 1701 (42000)で失敗、元の親行は残りました。子行だけは失われています。
子が空の後に明示transactionで親をDELETEすると0件になり、ROLLBACKで元の親行が復元しましたが、先行TRUNCATEで消した子行は戻りませんでした。別のFKなし表ではSTART TRANSACTION、別表INSERT、対象表INSERT、TRUNCATE、ROLLBACKの後も対象表は0件で、先行する別表INSERTは確定済みでした。合成表の自動採番は42まで進めた後、TRUNCATE後の実INSERTで1を確認しました。これは当該検体の設定に限る結果です。
これは旧記事のコードやこのページの参照先確認SQLを実行した証拠ではありません。Oracle・PostgreSQL・SQL Serverのruntime、Oracle identity、障害復旧や性能は未検証です。
この新規読取SQLは記事向けの追加例で、上記の合成runtimeで実行したSQLではありません。
AUTO_INCREMENT / シーケンスの挙動
採番は製品と定義を分けて確認します。MySQL 8.4はAUTO_INCREMENTを開始値へ戻しますが、セッションのincrement/offset等によって次の実値を常に1とは断定できません。SQL Serverのidentityは定義したseedへ戻るため、seedが1でなければ1ではありません。Oracle 19cのidentityについてはこの検証で確定しておらず、MySQLの結果を転用しません。独立したsequenceまでTRUNCATEで一律resetされるわけではありません。
旧MySQL採番例を保持しています。事前定義した専用の空の表tで通常のAUTO_INCREMENT開始・増分条件を仮定した例で、表定義は省略されています。既存行や設定が違えば同じIDを保証しません。Oracle identityや独立sequenceの実測ではありません。
-- MySQL
INSERT INTO t (name) VALUES ('a'),('b'),('c'); -- id = 1,2,3
DELETE FROM t;
INSERT INTO t (name) VALUES ('d'); -- id = 4 (続きから)
TRUNCATE TABLE t;
INSERT INTO t (name) VALUES ('e'); -- id = 1 (1 に戻る)
PostgreSQL 18は既定CONTINUE IDENTITYです。RESTART IDENTITYは対象表の列に所有されるsequenceを再開させる指定で、独立sequenceすべてのresetではありません。再開処理自体もtransactionalですが、そのtransaction内で得たcurrval()の状態にはROLLBACK後の注意があります。採番を戻す必要性と並行利用を別に確認します。
権限とレプリケーション
必要な権限は製品別です。MySQL 8.4はDROP権限、Oracle 19cは自己schema内の表またはDROP ANY TABLEが条件です。PostgreSQL 18はTRUNCATE権限、SQL Server Database Engineは最低ALTER権限を要します。DELETEできることとTRUNCATEの許可は同義ではありません。一覧確認やエラー解消のためにDROP ANY TABLE等の広い権限を自動付与せず、まず対象と実効権限を確認します。
MySQL 8.4のTRUNCATEはbinary logging/replication上もDDLとしてstatement形式で記録されます。ただしDELETEが常に全行のrow imageになるわけではなく、binlog_format等の条件が異なります。ログ量だけからレプリカ遅延や負荷の少なさは保証できません。metadata lock・レプリカ側DDL・利用中の表・復旧要件を確認します。SQL Serverではtransactional/merge replicationで公開される表はTRUNCATEの制限対象です。他製品まで「常にレプリケーションにやさしい」と一般化しません。
FAQ
Q: TRUNCATE したデータは復旧できますか?
A: MySQL 8.4とOracle 19cの通常永続表は利用者のROLLBACKでは復元できません。OracleではTRUNCATE後にFLASHBACK TABLEで内容を戻すこともできません。復旧は利用可能なバックアップ・ログ保存・製品の復旧方式・対象時点と復元テスト次第で、binlogやREDOログがあるだけでは復旧できると保証しません。退避だけでなく、実行対象と件数の事前確認、作業の分離、復元可能性の確認を組み合わせます。バックアップだけが唯一の保険という説明は不十分です。
Q: 一部の行だけ消したいのですが
A: TRUNCATE に WHERE はありません。DELETE FROM t WHERE ... を使ってください。
Q: TRUNCATE のあと領域は解放されますか?
A: MySQL InnoDBのfile-per-table tablespaceではTRUNCATEが既存tablespaceを削除・再作成します。共有tablespaceのOSファイルが同じように縮小するとは限りません。SQL Serverでは物理的な解放がCOMMIT後へ遅延する場合があります。全製品で直ちに同量の空きディスクが得られるとは保証しません。
Q: 全部の表をまとめて空にしたい
A: 依存順だけで親TRUNCATEの制約は解除されません。子表の先行TRUNCATE、FK検査の解除、CASCADEへの切替を機械的に選ばず、対象・保持すべき行・参照定義・権限・取消範囲を先に確定します。複数TRUNCATEをtransactionで囲んでもMySQLやOracle通常表の一括取消にはなりません。実行可否が未確定なら書込みを止め、読取確認と復旧計画を先に行います。
製品別の条件は公式資料で確認できます:MySQL 8.4 TRUNCATE TABLE / MySQL 8.4 外部キー / MySQL 8.4 KEY_COLUMN_USAGE / Oracle 19c TRUNCATE TABLE / Oracle 19c CREATE TRIGGER / Oracle 19c COMMIT / PostgreSQL 18 TRUNCATE / SQL Server TRUNCATE TABLE(製品別適用条件を含む)。確認範囲はTRUNCATEの参照・取消・トリガ・採番と上記メタデータです。Oracle identityの次値は本記事では未確定として扱います。
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスのソフト一覧|Blender・Metasequoiaと用途別の選び方
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Oracle 19cのDROP INDEX|制約依存・ONLINEとINVISIBLE 2026-10-26 17:21:20
- Oracle 19cのDROP TABLE|CASCADE・PURGEと復旧条件 2026-10-26 17:21:20
- Oracle 19cのカラム削除|DROP COLUMN・SET UNUSEDと依存・取消条件 2026-10-26 17:21:19
- Oracle 19cの索引操作|作成・再構築・削除と製品別の比較 2026-10-26 16:39:47
- Oracle 19cの表DDL|表操作の選び方とCREATE・ALTER・DROP・TRUNCATE 2026-10-26 16:39:47
- TRUNCATE TABLEの注意点|空の子表でも残る外部キーと製品別の取消条件 2026-10-26 16:39:45
- Oracle 19cのSAVEPOINT|部分ロールバック・COMMIT・DDLの境界 2026-10-26 15:51:40
- Oracle 19cのUPDATE文|更新件数・NULL・相関サブクエリ・MERGE 2026-10-26 15:51:40
- Oracle 19cのHAVING句|WHEREとの違い・NULL・集計条件 2026-10-26 15:51:40
- Oracleの制約|NOT NULL・UNIQUE・主キー・外部キー・CHECK 2026-10-26 15:51:38
- Oracle SQL関数まとめ|集計・文字列・日時・NULL・分析関数 2026-10-26 15:51:38
- Oracle 19cのROLLBACK|SAVEPOINT・DDLの暗黙COMMITと製品別の違い 2026-10-26 14:28:53
- Oracle 19cのDDLとは|CREATE・ALTER・DROPと暗黙COMMITの注意点 2026-10-26 14:28:53
- Unityで処理を一定時間待つ|WaitForSeconds・実時間待機と停止条件 2026-10-26 12:51:07
- Unityのビルドに時間がかかる場合の対処法|ログ・照明・シェーダーの確認 2026-10-26 12:51:07