9.6 Dropping Databases and Schemas Safely
Right, let’s talk about breaking things. Specifically, let’s talk about how to break things safely by dropping databases and schemas. This isn’t a “click yes on the warning dialog” situation. This is the database equivalent of defusing a bomb. Snip the wrong wire—or execute the wrong command without thinking—and you’ll have a very, very quiet (and very, very empty) server. The DROP command is the most ruthlessly efficient command in SQL. It doesn’t move things to a trash can. It doesn’t ask for a second opinion. It incinerates the object and scatters the ashes. So let’s learn how to wield this power without setting your entire project on fire.
The Nuclear Option: DROP DATABASE
The command itself is brutally simple.
DROP DATABASE IF EXISTS my_old_project;
See? Simple. Terrifying. The IF EXISTS clause is your first and best friend here. It turns a fatal error (if the database doesn’t exist) into a harmless warning. Always use it. There is literally no downside.
Now, here’s the first “questionable choice” by the designers. You can’t just drop any database. You can’t drop the one you’re currently connected to. This seems logical until you’re the one staring at a error message, realizing you’re locked in a room with no door. To drop a database, you must first connect to another database, like the default postgres or template1.
-- This will FAIL spectacularly if you are connected to 'doomed_db'
DROP DATABASE doomed_db;
-- First, connect to a different database
\c postgres; -- This is the meta-command in psql. In other tools, just reconnect.
-- Now you can drop it
DROP DATABASE IF EXISTS doomed_db;
The Subtle Knife: DROP SCHEMA
Schemas are namespaces within a database. Dropping one is just as permanent but slightly less dramatic than nuking a whole database. The same rules apply: you can’t drop a schema if it’s not empty, unless you tell the database to incinerate everything inside it first.
-- This will fail if the schema contains any objects (tables, views, etc.)
DROP SCHEMA IF EXISTS my_old_schema;
-- This is the "I know what I'm doing, please incinerate everything" command
DROP SCHEMA IF EXISTS my_old_schema CASCADE;
Ah, CASCADE. The most powerful, most dangerous word in the entire SQL lexicon. It doesn’t just drop the schema; it drops every single object inside the schema—all its tables, views, functions, you name it—and then drops the schema itself. It will also drop any objects in other schemas that depend on objects in the one you’re dropping. The database will follow these dependency chains ruthlessly. Using CASCADE is like using a grenade to clean your desk. Effective, but with significant collateral damage.
The Pre-Flight Checklist: What to Do Before You Drop
Never, ever run a DROP command without doing these two things first.
Take a Backup. I’m serious. Even if it’s a disposable test database, make a habit of it. Run
pg_dump my_old_project > my_old_project_backup.sql. This isn’t a sign of weakness; it’s a sign of not being an idiot. One day, you will mistype a database name. The backup will be your get-out-of-jail-free card.Be Paranoically Specific. The horror stories always start with a typo. You meant to drop
db_oldbut your finger slipped and you droppeddb_prod. The way to combat this is with an almost comedic level of specificity. Connect to the exact right host. Check your connection string twice. Use fully qualified names in your scripts.
A Safer Alternative: The Rename-and-Drop Gambit
Here’s a pro-tier trick. Instead of dropping immediately, rename the object first. This is the ultimate safety net.
-- First, disconnect all users from the target database
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'doomed_db';
-- Rename it to something obviously disposable
ALTER DATABASE doomed_db RENAME TO doomed_db_zombie_20231027;
-- ...Wait a day. Or a week. Does anything break? No? Good.
-- Then, and only then, drop it.
DROP DATABASE doomed_db_zombie_20231027;
This achieves two things: First, it instantly makes the database invisible to any applications that might still be trying to connect to it (they’ll error out immediately, which is a great way to find out you were wrong about it being unused). Second, it gives you a cooling-off period. If you made a catastrophic mistake, you can just rename it back. Once you’re absolutely certain, then you drop the zombified corpse. This practice has saved my bacon more times than I care to admit.