MySQL Truncate Table
TRUNCATE TABLE removes all rows from a table in one fast operation and leaves the empty table in place, ready for new data. It is perfect for clearing staging, log or test tables. It behaves quite differently from DELETE, though, and those differences matter.
1. Syntax
TRUNCATE [TABLE] table_name;
- The word
TABLEis optional. - Only one table per statement.
- Needs the
DROPprivilege on the table. - It is a DDL statement and commits implicitly.
TRUNCATE is fast because it recreates the table instead of deleting rows one at a time.2. Emptying a Table
SELECT * FROM app_logs;
Before
| log_id | level | message |
|---|---|---|
| 1 | INFO | started |
| 2 | WARN | slow query |
| 3 | ERROR | timeout |
| 4 | INFO | stopped |
TRUNCATE TABLE app_logs;
Query OK, 0 rows affected
SELECT COUNT(*) AS rows_left FROM app_logs;
DESCRIBE app_logs;
Result: 1 row
| rows_left |
|---|
| 0 |
Result: 3 rows
| Field | Type | Key | Extra |
|---|---|---|---|
| log_id | int | PRI | auto_increment |
| level | varchar(5) | ||
| message | varchar(100) |
The rows are gone but the structure (columns, keys, AUTO_INCREMENT) is intact.
3. AUTO_INCREMENT Is Reset
After TRUNCATE, numbering starts again at 1. After DELETE, it continues from where it was:
INSERT INTO app_logs (level, message) VALUES ('INFO', 'after truncate');
SELECT log_id, message FROM app_logs;
Result: 1 row
| log_id | message |
|---|---|
| 1 | after truncate |
CREATE TABLE app_logs_d LIKE app_logs;
INSERT INTO app_logs_d (level, message) VALUES ('INFO','a'),('INFO','b'),('INFO','c');
DELETE FROM app_logs_d;
INSERT INTO app_logs_d (level, message) VALUES ('INFO', 'after delete');
SELECT log_id, message FROM app_logs_d;
Result: 1 row
| log_id | message |
|---|---|
| 4 | after delete |
4. TRUNCATE Can't Be Rolled Back
INSERT INTO app_logs (level, message) VALUES ('INFO','x'),('INFO','y');
START TRANSACTION;
TRUNCATE TABLE app_logs; -- implicit COMMIT happens here
ROLLBACK;
SELECT COUNT(*) AS rows_after_rollback FROM app_logs;
Result: 1 row
| rows_after_rollback |
|---|
| 0 |
The ROLLBACK has nothing to undo. With DELETE inside a transaction, the rows would come back.
5. TRUNCATE and Foreign Keys
InnoDB refuses to truncate a table that is referenced by another table's foreign key, even if the child table is empty:
CREATE TABLE customers (id INT PRIMARY KEY, name VARCHAR(30));
CREATE TABLE invoices (id INT PRIMARY KEY, customer_id INT,
FOREIGN KEY (customer_id) REFERENCES customers(id));
INSERT INTO customers VALUES (1, 'Rhea');
TRUNCATE TABLE customers;
Query OK, 0 rows affected
Query OK, 0 rows affected
Query OK, 1 row affected
ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint (`appdb`.`invoices`, CONSTRAINT `invoices_ibfk_1`)
Options: truncate in a maintenance window with checks disabled, or use DELETE, which respects the foreign keys row by row:
SET foreign_key_checks = 0;
TRUNCATE TABLE customers;
SET foreign_key_checks = 1;
SELECT COUNT(*) AS customers_left FROM customers;
Result: 1 row
| customers_left |
|---|
| 0 |
6. Triggers Don't Fire
A DELETE trigger runs for every deleted row; TRUNCATE skips it:
CREATE TABLE deleted_log (msg VARCHAR(50));
CREATE TABLE notes (id INT PRIMARY KEY, txt VARCHAR(30));
CREATE TRIGGER notes_ad AFTER DELETE ON notes
FOR EACH ROW INSERT INTO deleted_log VALUES (CONCAT('deleted note ', OLD.id));
INSERT INTO notes VALUES (1,'a'),(2,'b');
DELETE FROM notes WHERE id = 1;
TRUNCATE TABLE notes;
SELECT * FROM deleted_log;
Result: 1 row
| msg |
|---|
| deleted note 1 |
Only the DELETE was logged. If your audit relies on triggers, don't use TRUNCATE.
7. TRUNCATE vs DELETE vs DROP
| TRUNCATE | DELETE (no WHERE) | DROP | |
|---|---|---|---|
| Removes | All rows | All rows (or filtered) | Rows and table |
| Table remains | Yes | Yes | No |
| Speed on large tables | Very fast | Slow | Very fast |
| Rollback | No | Yes | No |
| AUTO_INCREMENT | Reset to 1 | Continues | Gone |
| Triggers | Not fired | Fired per row | Dropped |
| Referenced by a foreign key | Refused | Allowed (rules apply) | Refused |
| Rows affected reported | 0 | Number deleted | 0 |
8. When to Use TRUNCATE
- Clearing staging tables before a nightly import.
- Resetting test data between test runs.
- Emptying log or cache tables that nothing references.
- Not for removing some rows, for tables with audit triggers, or when you might need to roll back.
9. Summary
TRUNCATE TABLE t;removes all rows quickly and keeps the structure.- It resets AUTO_INCREMENT, skips triggers and can't be rolled back.
- InnoDB won't truncate a table referenced by a foreign key.
- Use
DELETEwhen you need a WHERE clause, triggers or a rollback; useDROPto remove the table entirely.