Comando Soltar todas las tablas

83

¿Cuál es el comando para eliminar todas las tablas en SQLite?

Del mismo modo, me gustaría eliminar todos los índices.

alamodey
fuente

Respuestas:

82

No creo que pueda eliminar todas las tablas de un solo golpe, pero puede hacer lo siguiente para obtener los comandos:

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

El resultado de esto es un script que le quitará las tablas. Para índices, simplemente reemplace table con index.

Puede utilizar otras cláusulas en la wheresección para limitar qué tablas o índices se seleccionan (como " and name glob 'pax_*'" para los que comienzan con "pax_").

Puede combinar la creación de este script con su ejecución en un script bash (o cmd.exe) simple para que solo haya un comando para ejecutar.

Si no se preocupan por cualquiera de la información en la base de datos, creo que sólo se puede eliminar el archivo se almacena en el disco duro fuera - que es probablemente más rápido. Nunca he probado esto, pero no veo por qué no funcionaría.

paxdiablo
fuente
Gracias. Es muy extraño que no haya un comando simple, sino esta consulta SQL hacky.
alamodey
7
Bueno, la forma más fácil de obtener una base de datos sqlite vacía es simplemente eliminar el archivo y luego conectarse a él ..
John Fouhy
2
De ahí mi párrafo final, @JF.
paxdiablo
¿Qué sucede con los disparadores conectados a una mesa?
RDS
@rds, cuando sueltas una tabla, todos los desencadenantes de la misma también se eliminan. Tiene poco sentido mantener los disparadores cuando no es posible que se activen (ya que la mesa ya no existe).
paxdiablo
80

Si bien es cierto que no existe el comando DROP ALL TABLES, puede usar el siguiente conjunto de comandos.

Nota: Estos comandos tienen el potencial de dañar su base de datos, así que asegúrese de tener una copia de seguridad.

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

luego desea recuperar el espacio eliminado con

VACUUM;

y una buena prueba para asegurarse de que todo esté bien

PRAGMA INTEGRITY_CHECK;
Noé
fuente
1
¿Cómo ejecutarlos en onUpgrade ()?
AZ_
Simplemente ejecute el DDL, eso es suficiente
Noah
En caso de que por alguna loca razón alguien más tenga esta pregunta, lo anterior funciona para eliminar todas las tablas en la API de base de datos de Titanium Mobile.
Riley Dutton
2
Increíblemente inteligente. Nuestro sistema de actualización incremental de cosecha propia solo puede ejecutar scripts que comparan versiones, este truco no requiere ninguna mejora :)
Ivan G.
3
NOTA: esto puede producir extraños problemas de "archivo de base de datos con formato incorrecto" en un segundo intento de limpiar la base de datos (al menos con el último sqlite), pero parece funcionar perfectamente si usa algo como delete from sqlite_master where type in ('table', 'index', 'trigger').
mlvljr
36
rm db/development.sqlite3
alamodey
fuente
sí, esto elimina la base de datos, pero puede haber otras cosas en sqlite además de las tablas; Vea mi respuesta completa para más detalles
Noah
9
Si la base de datos tiene múltiples conexiones abiertas, esto no funcionará. En un * nix que simplemente eliminará el nombre, y las conexiones continuarán trabajando con el archivo de base de datos sin nombre hasta que cierren sus identificadores. Si la intención es reescribir el esquema (eliminar todas las tablas, crear nuevas tablas), entonces tendrá problemas.
jbarlow
3
Esta no debería ser la respuesta aceptada, ya que eliminó la base de datos, que incluye todos los procedimientos almacenados, activadores, etc., no solo las tablas.
Hobbyist
2
Creo que esta respuesta responde a la pregunta que el cartel pretendía hacer, que es: "¿Cómo puedo empezar de cero fácilmente con mi base de datos sqlite?" Alguien probablemente debería editar la pregunta para que sea más clara ... si eso es posible.
Akrikos
22

Tuve el mismo problema con SQLite y Android. Aquí está mi solución:

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

Me gustaría agregar a otras respuestas que implican eliminar tablas y no eliminar el archivo, que también puede ejecutar delete from sqlite_sequencepara restablecer las secuencias de incremento automático.

Flavio Tordini
fuente
3

Una vez que haya eliminado todas las tablas (y los índices desaparecerán cuando la tabla se vaya), no queda nada en una base de datos SQLite que yo sepa, aunque el archivo no parece encogerse (de una prueba rápida que acabo de hacer ).

Por lo tanto, eliminar el archivo parecería ser más rápido; simplemente debería volver a crearse cuando su aplicación intente acceder al archivo db.

Mike Woodhouse
fuente
1
El archivo no se encoge porque esa no es la forma en que funciona sqlite; solo devolverá espacio en disco al sistema operativo si aspira el archivo (básicamente lo vuelve a crear desde cero). Hasta entonces, el archivo está lleno de espacio reutilizable.
paxdiablo
Yah. Por lo tanto, eliminar todas las tablas y pasar la aspiradora tendría sentido si no tuviera privilegios de eliminación / creación de archivos, o si hubiera una situación extraña de múltiples usuarios. De lo contrario, ¿simplemente eliminar la cosa?
Mike Woodhouse
3

Usando 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]))
usuario3467349
fuente
2

Tuve este problema en Android y escribí un método similar a it-west.

Debido a que usé AUTOINCREMENTclaves primarias en mis tablas, hubo una tabla llamada sqlite_sequence. SQLite se bloqueaba cuando la rutina intentaba eliminar esa tabla. Tampoco pude captar la excepción. Mirando https://www.sqlite.org/fileformat.html#internal_schema_objects , descubrí que podría haber varias de estas tablas de esquemas internos que no quería eliminar. La documentación dice que cualquiera de estas tablas tiene nombres que comienzan con sqlite_ así que escribí este método

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

No puedo decir que esta sea la solución más portátil o a prueba de balas, pero funciona para mis scripts de prueba:

.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

Este fragmento de código redirige la salida a un archivo temporal, construye los comandos de 'drop table' que quiero ejecutar (enviando los comandos al archivo temporal), establece la salida de nuevo a la salida estándar, luego ejecuta los comandos del archivo y finalmente elimina el archivo.

Matt Malone
fuente
0

O en un indicador de shell, en solo dos líneas, sin un archivo temporal con nombre, asumiendo que $ db es el nombre de la base de datos SQLite:

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