- SQL
DELETE・TRUNCATE・DROPの違い|DB別ロールバック可否の比較表
DELETE・TRUNCATE・DROPの違いは、「何が消えるか」です。DELETEは条件に合う行、TRUNCATEはテーブルの全行、DROPはテーブルそのもの(定義・インデックス・権限ごと)を消します。 どれも「データを消す」命令ですが、ロールバックできるか、連番(AUTO_INCREMENT・IDENTITY)が戻るか、トリガーが動くか、外部キーがあるときにどうなるかは、命令とデータベースの組み合わせで変わります。
特に 「TRUNCATEはロールバックできるか」はDBによって答えが逆 です。PostgreSQLでは取り消せ、MySQLでは取り消せません。この記事では PostgreSQL 16.15 と MySQL 8.0.46 で実際に実行した結果(エラー全文、連番の値、100万行の削除時間)を載せ、SQL Server・Oracle は公式ドキュメントで確認した内容を比較表に加えています。最後に、誤って消したときに備える書き方と運用もまとめます。
MySQL 8.0 は2026年4月にサポートが終了しています。本記事の検証は手元の 8.0.46 で行いましたが、ここで扱う DELETE・TRUNCATE・DROP の動きと書き方は MySQL 8.4/9.7 でも同じ手順で使えます(違いがある箇所は本文で明記します)。
DELETE・TRUNCATE・DROPの違い早見表
| 項目 | DELETE | TRUNCATE | DROP |
|---|---|---|---|
| 消えるもの | 条件に合う行 | 全行(テーブル定義は残る) | テーブル定義・データ・インデックス・トリガー・権限 |
| WHERE句 | 使える | 使えない | 使えない |
| 分類 | DML(データ操作) | DDL扱い(PostgreSQLはトランザクション内で取り消せる) | DDL(定義操作) |
| ロールバック | 全DBで可 | PostgreSQL・SQL Serverは可/MySQL・Oracleは不可 | PostgreSQL・SQL Serverは可/MySQL・Oracleは不可 |
| 連番(AUTO_INCREMENT等) | 戻らない | MySQL・SQL Serverは1に戻る/PostgreSQLは RESTART IDENTITY 指定時のみ |
テーブルごと消える |
| DELETEトリガー | 動く | 動かない(PostgreSQLは ON TRUNCATE トリガーあり) |
動かない(トリガーも消える) |
| 外部キーで参照されている | 参照中の行はエラー(ON DELETE 設定に従う) |
エラー(PostgreSQL・Oracleは CASCADE あり) |
エラー(PostgreSQLは CASCADE で制約ごと削除) |
| 速度(100万行・MySQL 8.0) | 3.60〜3.67秒 | 0.05〜0.11秒 | 0.07〜0.26秒 |
| 速度(100万行・PostgreSQL 16) | 460〜516ミリ秒 | 34〜45ミリ秒 | 14〜27ミリ秒 |
| ディスク領域 | すぐには減らない | すぐ解放 | すぐ解放 |
| 必要な権限 | DELETE | PostgreSQL:TRUNCATE/MySQL:DROP/SQL Server:ALTER | DROP(所有者など) |
| ログ | 1行ずつ記録 | ページ単位などで最小限 | 最小限 |
迷ったときの選び方
| やりたいこと | 使う命令 |
|---|---|
| 一部の行だけ消す | DELETE ... WHERE |
| 全行を消して、連番もトリガーも気にしない | TRUNCATE |
| 全行を消すが、DELETEトリガーで履歴を残したい | DELETE(WHERE なし) |
| テーブル自体が不要になった | DROP TABLE IF EXISTS |
| 間違えたら戻したい(MySQL) | DELETE をトランザクション内で実行 |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「DELETE・TRUNCATE・DROPの違い|DB別ロールバック可否の比較表」
それぞれの基本構文
-- DELETE:条件に合う行を消す(WHERE を省くと全行)
DELETE FROM tasks WHERE status = 'done';
-- TRUNCATE:全行を消す
TRUNCATE TABLE tasks; -- 全DB共通
TRUNCATE tasks RESTART IDENTITY; -- PostgreSQL:連番も1に戻す
TRUNCATE orders CASCADE; -- PostgreSQL:参照している表もまとめて空にする
-- DROP:テーブルを消す
DROP TABLE IF EXISTS tasks;
DELETEは行を1件ずつ削除して記録し、TRUNCATEはデータの入れ物(ページやファイル)をまとめて作り直すため速くなります。 この仕組みの違いが、ロールバック・連番・トリガーの違いにつながっています。
TRUNCATEとDROPはロールバックできるか(DB別に実行)
PostgreSQL 16:TRUNCATEもDROPも取り消せる
CREATE TABLE tasks (id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY, title text);
INSERT INTO tasks(title) VALUES ('a'),('b'),('c');
BEGIN;
TRUNCATE tasks;
SELECT count(*) AS in_tx FROM tasks;
ROLLBACK;
SELECT count(*) AS after_rollback FROM tasks;
BEGIN;
DROP TABLE tasks;
ROLLBACK;
SELECT count(*) AS after_drop_rollback FROM tasks;
実行結果(PostgreSQL 16.15)
in_tx
-------
0
after_rollback
----------------
3
after_drop_rollback
---------------------
3
PostgreSQLはDDLもトランザクションの中で扱えるため、BEGIN の後なら TRUNCATE も DROP TABLE も ROLLBACK で元に戻ります。
MySQL 8.0:TRUNCATEは暗黙コミットされる
MySQLでは TRUNCATE と DROP は「暗黙コミット」を起こす命令です。実行した時点で、それまでの変更も含めて確定します。
CREATE TABLE tasks (id int AUTO_INCREMENT PRIMARY KEY, title varchar(50));
CREATE TABLE members (id int PRIMARY KEY, name varchar(20));
INSERT INTO tasks(title) VALUES ('a'),('b'),('c');
INSERT INTO members VALUES (1,'m1'),(2,'m2');
START TRANSACTION;
DELETE FROM members WHERE id = 1; -- ① 取り消すつもりの DELETE
TRUNCATE TABLE tasks; -- ② ここで暗黙コミット
ROLLBACK;
SELECT (SELECT count(*) FROM members) AS members, (SELECT count(*) FROM tasks) AS tasks;
実行結果(MySQL 8.0.46)
+---------+-------+
| members | tasks |
+---------+-------+
| 1 | 0 |
+---------+-------+
TRUNCATE が空になったままなのに加えて、その前の DELETE FROM members まで確定しています(2件→1件)。 TRUNCATE の直前に暗黙のCOMMITが走り、トランザクションが終わっているためです。MySQLで「消した後に確認してから確定したい」ときは、TRUNCATE ではなく DELETE をトランザクション内で使います。
4DBのロールバック可否
| 命令 | PostgreSQL 16 | MySQL 8.0 | SQL Server | Oracle |
|---|---|---|---|---|
| DELETE | 可 | 可(InnoDB) | 可 | 可 |
| TRUNCATE | 可(実行で確認) | 不可・暗黙コミット(実行で確認) | 可(公式で確認) | 不可・暗黙コミット(公式で確認) |
| DROP TABLE | 可(実行で確認) | 不可・暗黙コミット | 可 | 不可。ただしごみ箱から FLASHBACK TABLE ... TO BEFORE DROP で戻せる場合あり |
SQL Server と Oracle の列は、各社の公式ドキュメントで確認した内容で、本記事の環境では実行していません。SQL Server の公式ドキュメントには BEGIN TRANSACTION 内の TRUNCATE TABLE を ROLLBACK で取り消す例があります。Oracle の公式ドキュメントでは、TRUNCATE 後の状態は FLASHBACK TABLE でも戻せないと説明されています。
連番(AUTO_INCREMENT・IDENTITY)はリセットされるか
MySQL 8.0:DELETEは続きから、TRUNCATEは1から
INSERT INTO tasks(title) VALUES ('a'),('b'),('c'); -- id 1〜3
DELETE FROM tasks;
INSERT INTO tasks(title) VALUES ('after delete');
SELECT * FROM tasks;
TRUNCATE TABLE tasks;
INSERT INTO tasks(title) VALUES ('after truncate');
SELECT * FROM tasks;
+----+--------------+
| id | title |
+----+--------------+
| 4 | after delete |
+----+--------------+
+----+----------------+
| id | title |
+----+----------------+
| 1 | after truncate |
+----+----------------+
PostgreSQL 16:TRUNCATEだけでは戻らない
DELETE FROM tasks;
INSERT INTO tasks(title) VALUES ('after delete');
SELECT * FROM tasks;
TRUNCATE tasks;
INSERT INTO tasks(title) VALUES ('after truncate');
SELECT * FROM tasks;
TRUNCATE tasks RESTART IDENTITY;
INSERT INTO tasks(title) VALUES ('after restart identity');
SELECT * FROM tasks;
id | title
----+--------------
4 | after delete
id | title
----+----------------
5 | after truncate
id | title
----+------------------------
1 | after restart identity
PostgreSQLの TRUNCATE は既定で CONTINUE IDENTITY(連番を続ける)です。1に戻したいときは RESTART IDENTITY を付けます。 連番だけを任意の値に合わせ直す方法(setval、ALTER TABLE ... RESTART)は「PostgreSQL連番|serialとIDENTITYの違いとsetval修正」の記事で詳しく扱っています。
| DB | DELETE後 | TRUNCATE後 | 連番だけ戻す方法 |
|---|---|---|---|
| PostgreSQL 16 | 続きから | 続きから(RESTART IDENTITY で1から) |
ALTER TABLE t ALTER COLUMN id RESTART WITH 1 |
| MySQL 8.0 | 続きから | 1から | ALTER TABLE t AUTO_INCREMENT = 1 |
| SQL Server(公式) | 続きから | 初期値(seed)に戻る | DBCC CHECKIDENT |
外部キーで参照されているテーブルを消す
注文(orders)と注文明細(order_items)のように、子テーブルから外部キーで参照されている親テーブルを消す場合です。
CREATE TABLE orders (id int PRIMARY KEY);
CREATE TABLE order_items (id int PRIMARY KEY, order_id int REFERENCES orders(id));
INSERT INTO orders VALUES (1),(2);
INSERT INTO order_items VALUES (10,1),(11,2);
PostgreSQL 16 のエラーと CASCADE
=> TRUNCATE orders;
ERROR: cannot truncate a table referenced in a foreign key constraint
DETAIL: Table "order_items" references "orders".
HINT: Truncate table "order_items" at the same time, or use TRUNCATE ... CASCADE.
=> DELETE FROM orders WHERE id=1;
ERROR: update or delete on table "orders" violates foreign key constraint "order_items_order_id_fkey" on table "order_items"
DETAIL: Key (id)=(1) is still referenced from table "order_items".
=> DROP TABLE orders;
ERROR: cannot drop table orders because other objects depend on it
DETAIL: constraint order_items_order_id_fkey on table order_items depends on table orders
HINT: Use DROP ... CASCADE to drop the dependent objects too.
CASCADE を付けると、それぞれ次のように動きました。
=> TRUNCATE orders CASCADE;
NOTICE: truncate cascades to table "order_items"
TRUNCATE TABLE
-- orders: 0件、order_items: 0件
=> DROP TABLE orders CASCADE;
NOTICE: drop cascades to constraint order_items_order_id_fkey on table order_items
DROP TABLE
-- order_items テーブルは残り、外部キー制約だけが消える
TRUNCATE ... CASCADE は子テーブルのデータも空にし、DROP ... CASCADE は子テーブルの外部キー制約を消します(子テーブル自体は残ります)。 どちらも影響が親テーブルの外に広がるため、NOTICE の内容を確認してから使います。
MySQL 8.0 のエラー
ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint (`t123`.`order_items`, CONSTRAINT `order_items_ibfk_1`)
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`t123`.`order_items`, CONSTRAINT `order_items_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`))
ERROR 3730 (HY000): Cannot drop table 'orders' referenced by a foreign key constraint 'order_items_ibfk_1' on table 'order_items'.
MySQLは子テーブル(order_items)を先に TRUNCATE して空にしても、親テーブルの TRUNCATE は ERROR 1701 のままでした。 MySQLの TRUNCATE には CASCADE がないため、親子をまとめて空にするときは次のどちらかにします。
-- 方法1:子→親の順に DELETE(ロールバックも可能)
START TRANSACTION;
DELETE FROM order_items;
DELETE FROM orders;
COMMIT;
-- 方法2:外部キーチェックをこのセッションだけ一時的に無効化
SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE TABLE order_items;
TRUNCATE TABLE orders;
SET FOREIGN_KEY_CHECKS = 1;
方法2で親テーブルの TRUNCATE が通り、orders が0件になることを確認しました。方法2は整合性チェックを止めるので、子テーブルも必ず一緒に空にすることがポイントです。親の行を消したときに子をどうするか(ON DELETE CASCADE・SET NULL・RESTRICT)は「外部キーON DELETE CASCADE|SET NULL・RESTRICT比較」の記事で比較しています。
DELETEトリガーはTRUNCATEで動かない
削除履歴をトリガーで記録しているテーブルで、DELETE と TRUNCATE を比べました。
PostgreSQL 16
CREATE TABLE task_log (op text, cnt int, at timestamptz DEFAULT now());
CREATE FUNCTION log_delete() RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN INSERT INTO task_log(op, cnt) VALUES (TG_OP, 1); RETURN OLD; END $$;
CREATE TRIGGER trg_tasks_delete AFTER DELETE ON tasks
FOR EACH ROW EXECUTE FUNCTION log_delete();
INSERT INTO tasks(title) VALUES ('x'),('y');
DELETE FROM tasks WHERE title = 'x'; -- 1件削除
TRUNCATE tasks; -- 残り1件を削除
SELECT op, cnt FROM task_log;
op | cnt
--------+-----
DELETE | 1
TRUNCATE で消えた 'y' の記録は残っていません。 PostgreSQLには TRUNCATE 専用のトリガー(文単位)があり、これを追加すると TRUNCATE したこと自体は記録できます。
CREATE FUNCTION log_truncate() RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN INSERT INTO task_log(op, cnt) VALUES (TG_OP, NULL); RETURN NULL; END $$;
CREATE TRIGGER trg_tasks_truncate AFTER TRUNCATE ON tasks
FOR EACH STATEMENT EXECUTE FUNCTION log_truncate();
INSERT INTO tasks(title) VALUES ('z');
TRUNCATE tasks;
SELECT op, cnt FROM task_log;
op | cnt
----------+-----
DELETE | 1
TRUNCATE |
MySQL 8.0
CREATE TABLE task_log (op varchar(10), task_id int);
CREATE TRIGGER trg_tasks_delete AFTER DELETE ON tasks
FOR EACH ROW INSERT INTO task_log VALUES ('DELETE', OLD.id);
INSERT INTO tasks(title) VALUES ('x'),('y');
DELETE FROM tasks WHERE title = 'x';
TRUNCATE TABLE tasks;
SELECT * FROM task_log;
+--------+---------+
| op | task_id |
+--------+---------+
| DELETE | 2 |
+--------+---------+
MySQLでも記録されたのは DELETE の1件だけです。MySQLには TRUNCATE 用のトリガーはありません。 削除のたびに履歴を残す必要があるテーブルでは、全件削除でも DELETE FROM を使います。トリガー関数の書き方は「PostgreSQLトリガー関数の書き方」の記事にまとめています。
100万行の削除時間を比べる
同じ構成の100万行テーブルを作り、DELETE(WHERE なし)・TRUNCATE・DROP の時間を2回ずつ測りました(同一コンテナ、他の処理と並行しているため目安の値です)。
-- PostgreSQL 16(psql の \timing on で計測)
CREATE TABLE big (id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY, note text, created_at timestamptz DEFAULT now());
INSERT INTO big(note) SELECT 'row-' || g FROM generate_series(1,1000000) g;
DELETE FROM big; -- 計測
-- 再投入して TRUNCATE big; を計測、再投入して DROP TABLE big; を計測
-- MySQL 8.0(mysql -vvv の表示時間で計測)
SET SESSION cte_max_recursion_depth = 2000000;
CREATE TABLE big (id int AUTO_INCREMENT PRIMARY KEY, note varchar(30), created_at datetime DEFAULT CURRENT_TIMESTAMP);
INSERT INTO big(note)
WITH RECURSIVE s(g) AS (SELECT 1 UNION ALL SELECT g+1 FROM s WHERE g < 1000000)
SELECT CONCAT('row-', g) FROM s;
DELETE FROM big; -- 計測
| 命令(100万行) | PostgreSQL 16.15(1回目/2回目) | MySQL 8.0.46(1回目/2回目) |
|---|---|---|
| DELETE | 460.445 ms / 516.247 ms | 3.67 sec / 3.60 sec |
| TRUNCATE | 44.695 ms / 34.169 ms | 0.05 sec / 0.11 sec |
| DROP TABLE | 27.103 ms / 13.603 ms | 0.07 sec / 0.26 sec |
どちらのDBでも TRUNCATE は DELETE より1桁以上速い結果でした。 DELETE は1行ずつ削除の記録(PostgreSQLのWAL、MySQLのundo/redoログ)を残し、インデックスからも1件ずつ外すためです。
さらに PostgreSQL ではディスク使用量にも差が出ました。
SELECT pg_size_pretty(pg_total_relation_size('big'));
| 時点 | テーブル+インデックスのサイズ |
|---|---|
| 100万行投入後 | 64 MB |
| DELETE 後 | 64 MB |
| TRUNCATE 後 | 16 kB |
DELETE した直後は領域が残り、VACUUM で再利用できる状態になってから使い回されます。TRUNCATE はファイルを作り直すため、その場で小さくなります。 削除後の領域の扱いは「PostgreSQLのVACUUMとautovacuum」の記事で詳しく説明しています。
必要な権限の違い
「DELETE権限を渡したのに TRUNCATE が通らない」というつまずきもよくあります。SELECT と DELETE だけを許可したユーザーで試しました。
-- PostgreSQL 16(GRANT SELECT, DELETE ON tasks TO t123_app;)
=> DELETE FROM tasks;
DELETE 0
=> TRUNCATE tasks;
ERROR: permission denied for table tasks
-- MySQL 8.0(GRANT SELECT, DELETE ON t123.tasks TO 't123_app'@'localhost';)
mysql> TRUNCATE TABLE tasks;
ERROR 1142 (42000): DROP command denied to user 't123_app'@'localhost' for table 'tasks'
| DB | DELETE | TRUNCATE | DROP TABLE |
|---|---|---|---|
| PostgreSQL | DELETE権限 | TRUNCATE権限(DELETEとは別) | 所有者 |
| MySQL | DELETE権限 | DROP権限 | DROP権限 |
| SQL Server(公式) | DELETE権限 | ALTER権限 | スキーマのALTER またはテーブルのCONTROL |
| Oracle(公式) | DELETE権限 | 自分のスキーマなら不要/他スキーマは DROP ANY TABLE | 自分のスキーマなら不要/他スキーマは DROP ANY TABLE |
アプリ用のユーザーには DELETE だけを渡し、TRUNCATE・DROP は管理用ユーザーに分けておくと、誤操作の影響範囲を小さくできます。 PostgreSQLの権限設計は「PostgreSQLのロールと権限」の記事でテンプレートを紹介しています。
SQL Server・Oracleを含めたDB別の違い
以下のうち SQL Server・Oracle の列は公式ドキュメントで確認した内容です(本記事では未実行)。
| 項目 | PostgreSQL 16 | MySQL 8.0 | SQL Server | Oracle |
|---|---|---|---|---|
| TRUNCATE のロールバック | 可 | 不可(暗黙コミット) | 可 | 不可(暗黙コミット) |
| TRUNCATE で連番 | 既定は継続、RESTART IDENTITY で初期化 |
初期化 | 初期値に戻る | 公式のTRUNCATE説明に記載なし |
| TRUNCATE の CASCADE | TRUNCATE ... CASCADE |
なし | なし | TRUNCATE TABLE ... CASCADE(ON DELETE CASCADE の子が対象) |
| 外部キー参照中の TRUNCATE | エラー | エラー(子が空でも) | エラー | エラー(自己参照を除く) |
| TRUNCATE とトリガー | ON TRUNCATE トリガーあり |
DELETEトリガーは動かない | トリガーは動かない | DELETEトリガーは動かない |
| 一部だけ TRUNCATE | パーティション単位で可 | ALTER TABLE ... TRUNCATE PARTITION |
WITH (PARTITIONS (2, 4)) |
ALTER TABLE ... TRUNCATE PARTITION |
| DROP 後の復元 | バックアップから | バックアップから | バックアップから | ごみ箱から FLASHBACK TABLE |
DROP TABLE IF EXISTS |
可 | 可 | 可(2016以降) | 可(23ai以降) |
誤って消したときに備える
書き方で備える
| 備え | 書き方の例 | 効果 |
|---|---|---|
| 先に件数を確認 | SELECT count(*) FROM tasks WHERE status='done'; → 同じ WHERE で DELETE |
WHERE の書き間違いに気づける |
| トランザクションで包む | BEGIN; DELETE ...; SELECT ...; COMMIT;(違えば ROLLBACK) |
確定前に結果を確認できる |
| 存在確認つきで消す | DROP TABLE IF EXISTS tmp_import; |
テーブルがなくてもエラーで止まらない |
| 削除前に退避 | CREATE TABLE tasks_bk AS SELECT * FROM tasks WHERE ...; |
消した行をすぐ戻せる |
| WHERE なし DELETE を防ぐ(MySQL) | SET SQL_SAFE_UPDATES = 1; |
キー列を使わない UPDATE・DELETE をエラーにする |
| 論理削除 | UPDATE tasks SET deleted_at = now() WHERE ...; |
行を残したまま非表示にする |
MySQLで TRUNCATE・DROP を使う前は、暗黙コミットで取り消せないことを前提に、退避テーブルかバックアップを先に用意します。 PostgreSQLなら BEGIN; を先に打っておくだけで、TRUNCATE や DROP でも結果を確認してから確定できます。
運用で備える
| 備え | 内容 |
|---|---|
| 権限の分離 | アプリ用ユーザーは SELECT・INSERT・UPDATE・DELETE のみ。TRUNCATE・DROP は管理用ユーザーだけ |
| 定期バックアップ | MySQLは mysqldump、PostgreSQLは pg_dump を定期実行し、リストア手順も試しておく |
| ポイントインタイムリカバリ | MySQLのバイナリログ、PostgreSQLのWALアーカイブで「消す直前」まで戻せるようにする |
| 接続先の明示 | 本番と検証で接続先の色やプロンプトを変え、どこに接続しているかを見てわかるようにする |
バックアップとリストアの具体的なコマンドは「mysqldumpバックアップとリストア」「pg_dump/pg_restoreの使い方」の記事で、オプション一覧とともに紹介しています。
よくある質問
Q. TRUNCATE はなぜ DELETE より速いのですか? A. DELETE は1行ずつ削除し、その記録とインデックスの更新を行います。TRUNCATE はテーブルのデータ領域をまとめて作り直すため、行数が多いほど差が開きます。本記事の100万行では PostgreSQL で約10倍以上、MySQL で約30倍以上の差がありました。
Q. TRUNCATE と「WHERE なしの DELETE」は結果が同じですか? A. 残るデータ(0件)は同じですが、連番の扱い、トリガー、ロールバック可否、権限、ディスク領域の解放が異なります。履歴トリガーがある表やMySQLで取り消したい場面では DELETE を選びます。
Q. MySQL 8.4 や 9.7 でも TRUNCATE はロールバックできませんか?
A. はい。8.4/9.7 でも TRUNCATE TABLE と DROP TABLE は暗黙コミットを起こす命令で、本記事と同じ手順・結果になります。確認したいときは本記事の START TRANSACTION から始まるSQLをそのまま実行してください。
Q. DROP TABLE したテーブルを戻す方法はありますか?
A. PostgreSQL と SQL Server はトランザクション内で実行していれば ROLLBACK できます。Oracle はごみ箱が有効なら FLASHBACK TABLE ... TO BEFORE DROP が使えます。それ以外はバックアップからのリストアになります。
まとめ
- DELETE は行、TRUNCATE は全行、DROP はテーブルそのものを消す
- TRUNCATE のロールバックは PostgreSQL・SQL Server が可、MySQL・Oracle は暗黙コミットで不可。MySQLではそれ以前の変更も確定する
- 連番は MySQL の TRUNCATE で1に戻り、PostgreSQL は
RESTART IDENTITYを付けたときだけ戻る - 外部キーで参照されている親テーブルは TRUNCATE できない。PostgreSQLは
CASCADE、MySQLは子→親の DELETE かFOREIGN_KEY_CHECKS - TRUNCATE では DELETE トリガーが動かない。履歴を残すなら DELETE、PostgreSQLなら
ON TRUNCATEトリガーも使える - 100万行では TRUNCATE が DELETE より1桁以上速く、PostgreSQLではディスク領域もすぐ解放された
- 権限の分離とバックアップ、トランザクション内での確認で、誤削除に備える
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「DELETE・TRUNCATE・DROPの違い|DB別ロールバック可否の比較表」
株式会社RJCでは、データベースの安全な操作方法を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。