102

What is the command to drop all tables in SQLite?

Similarly I'd like to drop all indexes.

Noah
  • 15,080
  • 13
  • 104
  • 148
alamodey
  • 14,320
  • 24
  • 86
  • 112

11 Answers11

99

While it is true that there is no DROP ALL TABLES command you can use the following set of commands.

Note: These commands have the potential to corrupt your database, so make sure you have a backup

PRAGMA writable_schema = 1;
delete from sqlite_master where type in ('table', 'index', 'trigger');
PRAGMA writable_schema = 0;

you then want to recover the deleted space with

VACUUM;

and a good test to make sure everything is ok

PRAGMA INTEGRITY_CHECK;
Matt
  • 74,352
  • 26
  • 153
  • 180
Noah
  • 15,080
  • 13
  • 104
  • 148
  • 1
    how to execute them in onUpgrade() ?? – AZ_ Feb 18 '11 at 10:57
  • Simply execute the DDL, that's enought – Noah Feb 26 '11 at 02:57
  • 3
    NOTE: this may give strange "database file is malformed" issues on a _second_ attempt to clean the database (at least with the latest sqlite), but seems to work flawlessly if you use something like `delete from sqlite_master where type in ('table', 'index', 'trigger')`. – mlvljr Oct 19 '12 at 19:19
  • This will have the side effect of dropping the `android_metadata` table as well. The next time the database is opened that table will be recreated, but to recreate it immediately you can flip write-ahead logging or foreign key constraints to the opposite of how you've got it configured, then flip it back. That will trigger an internal `reconfigure()` call that will write out the `android_metadata` table. – tophyr Jul 29 '15 at 21:58
  • @f470071 -- just add it to the where type in clause – Noah Sep 28 '15 at 21:23
  • According to https://www.sqlite.org/fileformat2.html#sqlite_master, `type` might also be "trigger". It's probably worth deleting those as well, I would think. But if you're deleting all of the types possible in `sqlite_master`, you might as well just `delete` without the `type` constraint. – spaaarky21 Jun 08 '16 at 17:47
  • At least for SQLite 3.12.2, this throws "table sqlite_master may not be modified" – rsaxvc Jul 16 '16 at 05:49
93

I don't think you can drop all tables in one hit but you can do the following to get the commands:

select 'drop table ' || name || ';' from sqlite_master
    where type = 'table';

The output of this is a script that will drop the tables for you. For indexes, just replace table with index.

You can use other clauses in the where section to limit which tables or indexes are selected (such as "and name glob 'pax_*'" for those starting with "pax_").

You could combine the creation of this script with the running of it in a simple bash (or cmd.exe) script so there's only one command to run.

If you don't care about any of the information in the DB, I think you can just delete the file it's stored in off the hard disk - that's probably faster. I've never tested this but I can't see why it wouldn't work.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
37
rm db/development.sqlite3
alamodey
  • 14,320
  • 24
  • 86
  • 112
  • yes, this does delete the database, but there can be other thing in sqlite besides tables; See my full answer for details – Noah Feb 14 '09 at 01:17
  • 11
    If the database has multiple connections open, this will not work. On a *nix that will just remove the name, and the connections will continue working with the unnamed database file until they are close their handles. If the intent is to rewrite the schema (drop all tables, make new tables) then you'll be in trouble. – jbarlow May 07 '11 at 02:39
  • 5
    This should not be the accepted answer, as it deleted the database, which includes all stored procedures, triggers, etc, not just the tables. – Hobbyist Jan 12 '16 at 23:07
  • 2
    I believe this answer does answer the question the poster meant to ask which is: "how do I easily start over from scratch with my sqlite database?" Someone should probably edit the question to be more clear... if that's possible. – Akrikos Apr 11 '17 at 20:15
  • The question was literally "Drop all tables command" originally. – Nora Söderlund May 21 '23 at 15:34
22

I had the same problem with SQLite and Android. Here is my Solution:

List<String> tables = new ArrayList<String>();
Cursor cursor = db.rawQuery("SELECT * FROM sqlite_master WHERE type='table';", null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
    String tableName = cursor.getString(1);
    if (!tableName.equals("android_metadata") &&
            !tableName.equals("sqlite_sequence"))
        tables.add(tableName);
    cursor.moveToNext();
}
cursor.close();

for(String tableName:tables) {
    db.execSQL("DROP TABLE IF EXISTS " + tableName);
}
it-west.net
  • 383
  • 1
  • 4
  • 8
6

Using pysqlite:

tables = list(cur.execute("select name from sqlite_master where type is 'table'"))

cur.executescript(';'.join(["drop table if exists %s" %i for i in tables]))
user3467349
  • 3,043
  • 4
  • 34
  • 61
  • Should not be the second line looks like this instead? cur.executescript(';'.join(["DROP TABLE IF EXISTS %s" %i[0] for i in tables])) I mean, the "i" is an sqlite3 object, but you need the name of the table – akoel Jun 10 '23 at 12:52
4

I'd like to add to other answers involving dropping tables and not deleting the file, that you can also execute delete from sqlite_sequence to reset auto-increment sequences.

Flavio Tordini
  • 535
  • 4
  • 11
3

Once you've dropped all the tables (and the indexes will disappear when the table goes) then there's nothing left in a SQLite database as far as I know, although the file doesn't seem to shrink (from a quick test I just did).

So deleting the file would seem to be fastest - it should just be recreated when your app tries to access the db file.

Mike Woodhouse
  • 51,832
  • 12
  • 88
  • 127
  • 1
    The file doesn't shrink because that's not the way sqlite works - it'll only return disk space to the OS if you vacuum the file (basically recreate it from scratch). Until then, the file is full of reusable space. – paxdiablo Feb 09 '09 at 04:07
  • Yah. So dropping all tables and vacuuming would make sense if you didn't have file delete/create privileges, or there was some strange multi-user situation. Otherwise just delete the thing? – Mike Woodhouse Feb 09 '09 at 09:48
2

I had this issue in Android and I wrote a method similar to it-west.

Because I used AUTOINCREMENT primary keys in my tables, there was a table called sqlite_sequence. SQLite would crash when the routine tried to drop that table. I couldn't catch the exception either. Looking at https://www.sqlite.org/fileformat.html#internal_schema_objects, I learned that there could be several of these internal schema tables that I didn't want to drop. The documentation says that any of these tables have names beginning with sqlite_ so I wrote this method

private void dropAllUserTables(SQLiteDatabase db) {
    Cursor cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);
    //noinspection TryFinallyCanBeTryWithResources not available with API < 19
    try {
        List<String> tables = new ArrayList<>(cursor.getCount());

        while (cursor.moveToNext()) {
            tables.add(cursor.getString(0));
        }

        for (String table : tables) {
            if (table.startsWith("sqlite_")) {
                continue;
            }
            db.execSQL("DROP TABLE IF EXISTS " + table);
            Log.v(LOG_TAG, "Dropped table " + table);
        }
    } finally {
        cursor.close();
    }
}
Jon
  • 9,156
  • 9
  • 56
  • 73
1

I can't say this is the most bulletproof or portable solution, but it works for my testing scripts:

.output /tmp/temp_drop_tables.sql
select 'drop table ' || name || ';' from sqlite_master where type = 'table';
.output stdout
.read /tmp/temp_drop_tables.sql
.system rm /tmp/temp_drop_tables.sql

This bit of code redirects output to a temporary file, constructs the 'drop table' commands that I want to run (sending the commands to the temp file), sets output back to standard out, then executes the commands from the file, and finally removes the file.

Matt Malone
  • 361
  • 4
  • 25
0

Or at a shell prompt, in just two lines, without a named temporary file, assuming $db is the SQLite database name:

echo "SELECT 'DROP TABLE ' || name ||';' FROM sqlite_master WHERE type = 'table';" |
    sqlite3 -readonly "$db" | sqlite3 "$db"
peak
  • 105,803
  • 17
  • 152
  • 177
0

To delete also views add 'view' keyword:

delete from sqlite_master where type in ('view', 'table', 'index', 'trigger');