DROP TABLE Syntax
DROP TABLE takes a table name (or comma-separated list of names in MySQL) and removes the table definition, all its rows, all its indexes, and all its triggers.
-- Drop a single table
DROP TABLE table_name;
-- Drop multiple tables at once (MySQL / PostgreSQL)
DROP TABLE table_one, table_two, table_three;
-- Examples
DROP TABLE temp_import_data;
DROP TABLE old_sessions;
There is no built-in undo. The table definition (schema) is gone, and all rows are gone. In MySQL's InnoDB, DROP TABLE causes an implicit commit — it cannot be rolled back even if you are inside a transaction. In PostgreSQL, DDL is transactional and can be rolled back within a transaction block. Always verify you have a recent backup before running DROP TABLE in production.
IF EXISTS
Attempting to drop a table that does not exist throws an error. The IF EXISTS clause prevents that error — the statement becomes a silent no-op if the table is missing. This is essential in migration and setup scripts.
-- Without IF EXISTS — errors if table does not exist
DROP TABLE old_logs; -- ERROR: Table 'old_logs' doesn't exist
-- With IF EXISTS — safe to run even if table is absent
DROP TABLE IF EXISTS old_logs; -- no error, no warning (or a note in MySQL)
-- Useful in setup/teardown scripts:
DROP TABLE IF EXISTS test_users;
DROP TABLE IF EXISTS test_orders;
CREATE TABLE test_users ( ... );
CREATE TABLE test_orders ( ... );
TRUNCATE vs DROP
When you only want to empty a table (delete all rows) but keep the table structure, use TRUNCATE instead of DROP.
-- TRUNCATE: removes all rows, keeps the table structure
TRUNCATE TABLE logs;
-- After TRUNCATE, logs still exists — it is just empty.
-- Auto-increment counters are reset to 1 (MySQL).
-- DROP: removes the table entirely
DROP TABLE logs;
-- After DROP, logs does not exist at all.
-- You would need CREATE TABLE to recreate it.
DELETE vs TRUNCATE
DELETE, TRUNCATE, and DROP all remove data, but in very different ways:
| Feature | DELETE | TRUNCATE | DROP |
|---|---|---|---|
| Removes rows | Yes (filtered or all) | Yes (all rows) | Yes (all rows) |
| Removes table structure | No | No | Yes |
| WHERE clause | Yes | No | No |
| Logged (row-level) | Yes — each row logged | Minimal logging | DDL log only |
| Rollback possible | Yes (in a transaction) | PostgreSQL: yes; MySQL: no | PostgreSQL: yes; MySQL: no |
| Resets AUTO_INCREMENT | No | Yes (MySQL) | N/A (table gone) |
| Speed on large tables | Slow | Very fast | Fast |
| Fires DELETE triggers | Yes | No | No |
-- DELETE: remove specific rows (can be rolled back)
DELETE FROM logs WHERE created_at < '2025-01-01';
-- DELETE all rows (slow on large tables, but rollback-safe)
DELETE FROM logs;
-- TRUNCATE: fast removal of all rows, reset auto-increment
TRUNCATE TABLE logs;
-- TRUNCATE with IF EXISTS (PostgreSQL supports this)
TRUNCATE TABLE IF EXISTS logs;
CASCADE
If other database objects depend on the table you want to drop — for example, views that query it or foreign keys that reference it — you may need CASCADE to force the drop and automatically remove those dependent objects too.
-- PostgreSQL: DROP TABLE with CASCADE drops dependent views and FKs
DROP TABLE users CASCADE;
-- This also drops any views that reference users, and removes
-- foreign key constraints in other tables that point to users.
-- PostgreSQL: RESTRICT (default) — refuses to drop if dependents exist
DROP TABLE users RESTRICT; -- error if anything depends on users
-- MySQL handles FK differently — disable FK checks first if needed:
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE users;
SET FOREIGN_KEY_CHECKS = 1;
-- Note: this does NOT drop the FK constraints in child tables —
-- you must clean those up manually.
In PostgreSQL, CASCADE will silently drop views, foreign key constraints, and other objects that depend on your table. Before running DROP TABLE ... CASCADE in production, query pg_depend or use \d+ tablename in psql to see all dependents. Dropping an unexpectedly shared base table with CASCADE can break unrelated parts of your application.
Production Safety Checklist
- Verify you have a recent backup — and confirm it can be restored.
- Double-check the table name — a typo can drop the wrong table.
- Check for dependent objects — views, foreign keys, application queries.
- Run in a transaction if your database supports DDL transactions (PostgreSQL) — allows rollback if something looks wrong.
- Test on a staging environment first using a production data snapshot.
- Consider soft-delete first — rename the table (e.g.,
RENAME TABLE users TO users_deprecated_20260608) and keep it for a few days before dropping permanently.
Summary
📋 Summary
DROP TABLEremoves the table structure and all its data permanently.IF EXISTSprevents errors in scripts when the table may or may not exist.- TRUNCATE empties a table (keeps structure), is much faster than
DELETEon large tables, and resets auto-increment. Not rollback-safe in MySQL. - DELETE removes rows (all or filtered), is fully logged and rollback-safe, fires triggers, but is slow on large tables.
- CASCADE (PostgreSQL) forces a drop even when dependent views or FKs exist — review dependents before using it.
- Always verify a working backup before running
DROP TABLEin production. Consider renaming the table first as a safety net.
FAQ
In general, no — not without a backup. In MySQL/InnoDB, DROP TABLE is not transactional (it causes an implicit commit), so there is no rollback. Some InnoDB recovery tools (like MySQL Enterprise Backup or third-party tools) can sometimes recover dropped tables from InnoDB data files if you act quickly before the space is reused — but this is complex, not guaranteed, and should never be relied on. In PostgreSQL, if you are inside an explicit BEGIN transaction block, you can ROLLBACK a DROP TABLE before committing. The best safety net is always a recent, tested backup.
DROP TABLE removes a single table (and its data) from the database. DROP DATABASE removes the entire database — every table, view, stored procedure, and all their data in one command. DROP DATABASE is even more destructive. Always use IF EXISTS with both commands in scripts, and exercise extreme caution in production.
TRUNCATE is a DDL operation — it deallocates and re-initialises the table's data pages, which includes resetting the auto-increment sequence to 1 (in MySQL). DELETE is a DML operation that removes rows one at a time through the transaction log; the auto-increment counter is a table-level setting and is not touched by DELETE. If you need to reset the counter after a DELETE, use ALTER TABLE t AUTO_INCREMENT = 1; in MySQL or ALTER SEQUENCE t_id_seq RESTART WITH 1; in PostgreSQL.
By default, no — most databases will refuse with an error like "Cannot drop table 'users' referenced by a foreign key constraint." You have three options: (1) Drop the child table first, then the parent. (2) Drop the foreign key constraint in the child table first with ALTER TABLE orders DROP FOREIGN KEY fk_orders_user;, then drop the parent table. (3) Use CASCADE in PostgreSQL which automatically drops the FK constraints. In MySQL, you can temporarily disable FK checks with SET FOREIGN_KEY_CHECKS = 0; — but remember to re-enable them and clean up orphaned FK definitions afterward.