Befehl "Alle Tabellen löschen"

83

Wie lautet der Befehl zum Löschen aller Tabellen in SQLite?

Ebenso möchte ich alle Indizes löschen.

Alamodey
quelle

Antworten:

81

Ich glaube nicht, dass Sie alle Tabellen mit einem Schlag löschen können, aber Sie können Folgendes tun, um die Befehle zu erhalten:

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

Die Ausgabe davon ist ein Skript, das die Tabellen für Sie löscht. Ersetzen Sie für Indizes einfach die Tabelle durch den Index.

Sie können andere Klauseln in diesem whereAbschnitt verwenden, um die Auswahl der ausgewählten Tabellen oder Indizes and name glob 'pax_*'einzuschränken (z. B. " " für diejenigen, die mit "pax_" beginnen).

Sie können die Erstellung dieses Skripts mit der Ausführung in einem einfachen Bash-Skript (oder cmd.exe-Skript) kombinieren, sodass nur ein Befehl ausgeführt werden muss.

Wenn Sie nicht über kümmern sich jede der Informationen in der DB, ich denke , man kann einfach die Datei löschen , es in von der Festplatte gespeichert ist - die wahrscheinlich schneller ist. Ich habe das noch nie getestet, aber ich kann nicht verstehen, warum es nicht funktionieren würde.

paxdiablo
quelle
Vielen Dank. Sehr seltsam, dass es keinen einfachen Befehl gibt, sondern diese hackige SQL-Abfrage.
Alamodey
6
Nun, der einfachste Weg, eine leere SQLite-Datenbank zu erhalten, besteht darin, die Datei zu löschen und dann eine Verbindung zu ihr
herzustellen
2
Daher mein letzter Absatz, @JF.
Paxdiablo
Was passiert mit Triggern, die an eine Tabelle angehängt sind?
rds
@rds, wenn Sie eine Tabelle löschen, werden auch alle Auslöser dafür gelöscht. Es macht wenig Sinn, Auslöser zu behalten, wenn sie unmöglich feuern können (da der Tisch nicht mehr existiert).
Paxdiablo
80

Obwohl es keinen Befehl DROP ALL TABLES gibt, können Sie die folgenden Befehle verwenden.

Hinweis: Diese Befehle können Ihre Datenbank möglicherweise beschädigen. Stellen Sie daher sicher, dass Sie über ein Backup verfügen

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

Sie möchten dann den gelöschten Speicherplatz mit wiederherstellen

VACUUM;

und ein guter Test, um sicherzustellen, dass alles in Ordnung ist

PRAGMA INTEGRITY_CHECK;
Noah
quelle
1
Wie führe ich sie in onUpgrade () aus?
AZ_
Führen Sie einfach die DDL aus, das ist genug
Noah
Falls aus irgendeinem verrückten Grund jemand anderes diese Frage hat, funktioniert das oben Genannte, um alle Tabellen in der Datenbank-API von Titanium Mobile zu löschen.
Riley Dutton
2
Unglaublich schlau. Unser selbst entwickeltes inkrementelles Upgrade-System kann nur Skripte ausführen, die Versionen vergleichen. Dieser Trick erfordert keine Verbesserungen :)
Ivan G.
3
HINWEIS: Dies kann bei einem zweiten Versuch, die Datenbank zu bereinigen (zumindest mit dem neuesten SQLite), zu seltsamen Problemen mit "Datenbankdatei ist fehlerhaft" führen , scheint jedoch einwandfrei zu funktionieren, wenn Sie so etwas verwenden delete from sqlite_master where type in ('table', 'index', 'trigger').
mlvljr
36
rm db/development.sqlite3
Alamodey
quelle
Ja, dies löscht zwar die Datenbank, aber es kann neben Tabellen noch etwas anderes in SQLite geben. Siehe meine vollständige Antwort für Details
Noah
9
Wenn in der Datenbank mehrere Verbindungen geöffnet sind, funktioniert dies nicht. Unter einem * nix wird nur der Name entfernt, und die Verbindungen arbeiten mit der unbenannten Datenbankdatei weiter, bis sie ihre Handles schließen. Wenn das Schema neu geschrieben werden soll (alle Tabellen löschen, neue Tabellen erstellen), treten Probleme auf.
Jbarlow
3
Dies sollte nicht die akzeptierte Antwort sein, da die Datenbank gelöscht wurde, die alle gespeicherten Prozeduren, Trigger usw. enthält, nicht nur die Tabellen.
Hobbyist
2
Ich glaube, diese Antwort beantwortet die Frage, die das Poster stellen sollte: "Wie kann ich mit meiner SQLite-Datenbank einfach von vorne anfangen?" Jemand sollte die Frage wahrscheinlich bearbeiten, um klarer zu sein ... wenn das möglich ist.
Akrikos
22

Ich hatte das gleiche Problem mit SQLite und Android. Hier ist meine Lösung:

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
quelle
4

Ich möchte zu anderen Antworten hinzufügen, bei denen Tabellen gelöscht und die Datei nicht gelöscht werden, die Sie auch ausführen können delete from sqlite_sequence, um automatische Inkrementierungssequenzen zurückzusetzen.

Flavio Tordini
quelle
3

Verwendung von 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
quelle
2

Sobald Sie alle Tabellen gelöscht haben (und die Indizes verschwinden, wenn die Tabelle gelöscht wird), ist meines Wissens nichts mehr in einer SQLite-Datenbank vorhanden, obwohl die Datei nicht zu schrumpfen scheint (nach einem kurzen Test, den ich gerade durchgeführt habe) ).

Das Löschen der Datei scheint also am schnellsten zu sein - sie sollte nur neu erstellt werden, wenn Ihre App versucht, auf die Datenbankdatei zuzugreifen.

Mike Woodhouse
quelle
1
Die Datei wird nicht verkleinert, da SQLite nicht so funktioniert. Der Speicherplatz wird nur dann an das Betriebssystem zurückgegeben, wenn Sie die Datei staubsaugen (im Grunde genommen von Grund auf neu erstellen). Bis dahin ist die Datei voll mit wiederverwendbarem Speicherplatz.
Paxdiablo
Yah. Das Löschen aller Tabellen und das Staubsaugen wäre also sinnvoll, wenn Sie keine Berechtigungen zum Löschen / Erstellen von Dateien hätten oder eine seltsame Mehrbenutzersituation vorliegt. Ansonsten einfach das Ding löschen?
Mike Woodhouse
2

Ich hatte dieses Problem in Android und habe eine ähnliche Methode wie it-west geschrieben.

Da ich AUTOINCREMENTin meinen Tabellen Primärschlüssel verwendet habe, wurde eine Tabelle aufgerufen sqlite_sequence. SQLite stürzte ab, wenn die Routine versuchte, diese Tabelle zu löschen. Ich konnte die Ausnahme auch nicht fangen. Unter https://www.sqlite.org/fileformat.html#internal_schema_objects habe ich festgestellt, dass es mehrere dieser internen Schematabellen geben kann , die ich nicht löschen wollte. Die Dokumentation besagt, dass jede dieser Tabellen Namen hat, die mit sqlite_ beginnen, also habe ich diese Methode geschrieben

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
quelle
1

Ich kann nicht sagen, dass dies die kugelsicherste oder tragbarste Lösung ist, aber sie funktioniert für meine Testskripte:

.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

Dieses Codebit leitet die Ausgabe in eine temporäre Datei um, erstellt die 'drop table'-Befehle, die ich ausführen möchte (Senden der Befehle an die temporäre Datei), setzt die Ausgabe wieder auf Standard out, führt dann die Befehle aus der Datei aus und schließlich entfernt die Datei.

Matt Malone
quelle
0

Oder an einer Shell-Eingabeaufforderung in nur zwei Zeilen ohne benannte temporäre Datei, vorausgesetzt, $ db ist der Name der SQLite-Datenbank:

echo "SELECT 'DROP TABLE ' || name ||';' FROM sqlite_master WHERE type = 'table';" |
    sqlite3 -readonly "$db" | sqlite3 "$db"
Gipfel
quelle