SQL4 min read7 sections

DELETE vs TRUNCATE vs DROP in SQL: the differences, with examples

Three commands that all make data disappear, and a very common interview question. This guide runs each one on the same small table so you can see exactly what is left afterwards.

Solve “Distinct departments”

Free. Runs in your browser, no install.

Updated Written for: Beginners and students preparing for SQL interview questions.

What you will learn

  • DELETE removes the rows you choose with WHERE. TRUNCATE removes all rows. DROP removes the whole table, rows and structure.
  • DELETE can be filtered and rolled back. TRUNCATE has no WHERE and is much faster on big tables.
  • Whether TRUNCATE can be rolled back depends on the database, so never rely on it as an undo button.
  • After DROP the table no longer exists, and any query on it fails.
On this page
  1. The table
  2. 1. DELETE: remove the rows you choose
  3. 2. DELETE inside a transaction can be rolled back
  4. 3. TRUNCATE: empty the whole table, fast
  5. 4. DROP: remove the table itself
  6. 5. The differences side by side
  7. Which one should I use?

"What is the difference between DELETE, TRUNCATE and DROP?" is one of the first SQL questions interviewers ask, because the three commands look similar and behave very differently. The short version: DELETE removes some rows, TRUNCATE empties the table, and DROP removes the table itself.

This guide runs all three on a small table. The statements ran in DuckDB, and each output is exactly what it printed. The differences in what each command can do are the same in every database, apart from the notes marked in the text.

DELETE
Some rows go

WHERE picks which.

The table stays.

Can be rolled back
TRUNCATE
All rows go

No WHERE.

An empty table stays.

Fast on big tables
DROP
Everything goes

Rows and the table.

Queries now fail.

Table is gone
Figure 1. What each command removes. DELETE keeps the table and the rows you do not choose. TRUNCATE keeps only the empty table. DROP keeps nothing.

The table

A small app_logs table with 6 rows from two services.

SQL
CREATE TABLE app_logs (
  log_id  INTEGER,
  service VARCHAR,
  level   VARCHAR,
  message VARCHAR
);

INSERT INTO app_logs VALUES
  (1, 'web', 'INFO',  'started'),
  (2, 'web', 'ERROR', 'timeout'),
  (3, 'api', 'INFO',  'started'),
  (4, 'api', 'ERROR', 'bad request'),
  (5, 'web', 'INFO',  'request ok'),
  (6, 'api', 'INFO',  'request ok');
SQL
SELECT COUNT(*) AS rows_in_table FROM app_logs;
rows_in_table
-------------
6
(1 row)

DELETE: remove the rows you choose

DELETE removes rows, and WHERE decides which. The table stays.

SQL
DELETE FROM app_logs WHERE level = 'INFO' AND service = 'web';
SQL
SELECT * FROM app_logs ORDER BY log_id;
log_id | service | level | message
-------+---------+-------+------------
2      | web     | ERROR | timeout
3      | api     | INFO  | started
4      | api     | ERROR | bad request
6      | api     | INFO  | request ok
(4 rows)

The two web INFO rows are gone and four remain. If you forget the WHERE, DELETE FROM app_logs removes every row, so many people write the WHERE first and run it as a SELECT before changing it to a DELETE. DELETE also works 1 row at a time behind the scenes and writes each removal to a log, which is why it is slower than TRUNCATE on a very large table, but it is also why it can be undone.

DELETE inside a transaction can be rolled back

A transaction is a group of statements that either all succeed or all get undone. Start one, delete, look, and then change your mind:

SQL
BEGIN TRANSACTION;
DELETE FROM app_logs WHERE service = 'api';
SQL
SELECT COUNT(*) AS rows_inside_transaction FROM app_logs;
rows_inside_transaction
-----------------------
1
(1 row)
SQL
ROLLBACK;
SQL
SELECT COUNT(*) AS rows_after_rollback FROM app_logs;
rows_after_rollback
-------------------
4
(1 row)

Inside the transaction the api rows were gone, and after ROLLBACK they were back. This ability to undo is the safety net that makes DELETE the careful choice.

TRUNCATE: empty the whole table, fast

TRUNCATE removes every row at once and keeps the empty table with its columns. It has no WHERE, so it cannot pick rows.

SQL
TRUNCATE app_logs;
SQL
SELECT COUNT(*) AS rows_after_truncate FROM app_logs;
rows_after_truncate
-------------------
0
(1 row)

Zero rows, but the table still exists and you can insert into it again. TRUNCATE is much faster than DELETE on large tables, because instead of removing rows one by one it resets the table's storage in a single step. In some databases it also resets the automatic counter of an auto-incrementing id back to 1.

DROP: remove the table itself

DROP TABLE removes the rows and the table: its columns, indexes and constraints are all gone. Afterwards the table does not exist.

SQL
DROP TABLE app_logs;
SQL
SELECT COUNT(*) FROM app_logs;
Catalog Error: Table with name app_logs does not exist!

The error is the proof: there is nothing left to query. To use the table again you must create it from scratch. DROP is a structure command. Whether it can be rolled back depends on the database: PostgreSQL and SQL Server can undo it inside a transaction, while MySQL and Oracle cannot. Treat it as permanent.

The differences side by side

DELETETRUNCATEDROP
RemovesChosen rowsAll rowsAll rows and the table
WHERE allowedYesNoNo
Table still existsYesYes, emptyNo
Speed on a huge tableSlowestFastFast
Can be rolled backYes, in a transactionDepends on the databaseDepends on the database
Type of commandDML (changes data)DDL (changes structure), in most databasesDDL

DML and DDL are labels interviewers like. DML (data manipulation language) changes the data: INSERT, UPDATE, DELETE. DDL (data definition language) changes the structure: CREATE, ALTER, DROP, and in most databases TRUNCATE.

Which one should I use?

  • Remove some rows, or you might need to undo it: DELETE with a careful WHERE.
  • Empty a table you will reuse, such as a staging table before a fresh load: TRUNCATE.
  • You no longer need the table at all: DROP.

One more rule that protects you: if other tables point at this one with foreign keys, the database may refuse DELETE or TRUNCATE until you remove those rows first, as shown in primary key vs foreign key. In a real job, run any destructive command on a copy or inside a transaction first, and check the row count before you commit to it.

Practise the related comparison in UNION vs UNION ALL counts, a free problem, or revisit SQL for beginners if WHERE is still new.

Keep practising

Take what you just read into the editor.

Browse all 36 guides