Команда удаления всех таблиц

Что такое команда, чтобы удалить все таблицы в SQLite?

Точно так же я хотел бы удалить все индексы.


person alamodey    schedule 08.02.2009    source источник


Ответы (11)


Я не думаю, что вы можете удалить все таблицы одним ударом, но вы можете сделать следующее, чтобы получить команды:

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

Результатом этого является скрипт, который удалит для вас таблицы. Для индексов просто замените таблицу на index.

Вы можете использовать другие предложения в разделе where, чтобы ограничить выбор таблиц или индексов (например, "and name glob 'pax_*'" для тех, которые начинаются с "pax_").

Вы можете совместить создание этого сценария с его запуском в простом сценарии bash (или cmd.exe), чтобы выполнить только одну команду.

Если вам не нужна какая-либо информация в БД, я думаю, вы можете просто удалить файл, в котором она хранится, с жесткого диска - это, вероятно, быстрее. Я никогда не проверял это, но я не понимаю, почему это не сработает.

person paxdiablo    schedule 08.02.2009
comment
Спасибо. Очень странно, что нет простой команды, а вместо этого хакерский SQL-запрос. - person alamodey; 08.02.2009
comment
Что ж, самый простой способ получить пустую базу данных sqlite — просто удалить файл, а затем подключиться к нему. - person John Fouhy; 09.02.2009
comment
Отсюда мой последний абзац, @JF. - person paxdiablo; 09.02.2009
comment
Что происходит с триггерами, прикрепленными к таблице? - person rds; 30.07.2015
comment
@rds, когда вы удаляете таблицу, все триггеры для нее также удаляются. Нет особого смысла хранить триггеры, когда они не могут сработать (поскольку таблицы больше не существует). - person paxdiablo; 30.07.2015
comment
как насчет игнорирования внешних ключей - person pleerock; 02.12.2016

Хотя это правда, что нет команды DROP ALL TABLES, вы можете использовать следующий набор команд.

Примечание. Эти команды могут повредить вашу базу данных, поэтому убедитесь, что у вас есть резервная копия.

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

затем вы хотите восстановить удаленное пространство с помощью

VACUUM;

и хороший тест, чтобы убедиться, что все в порядке

PRAGMA INTEGRITY_CHECK;
person Noah    schedule 14.02.2009
comment
как выполнить их в onUpgrade() ?? - person AZ_; 18.02.2011
comment
Просто выполните DDL, этого достаточно - person Noah; 26.02.2011
comment
В случае, если по какой-то сумасшедшей причине у кого-то еще возник этот вопрос, вышеизложенное работает, чтобы удалить все таблицы в API базы данных Titanium Mobile. - person Riley Dutton; 13.04.2011
comment
Невероятно умный. Наша доморощенная система инкрементального обновления может выполнять только скрипты, сравнивающие версии, этот трюк не требует никаких доработок :) - person Ivan G.; 26.03.2012
comment
ПРИМЕЧАНИЕ: это может привести к странным проблемам с искажением файла базы данных при второй попытке очистить базу данных (по крайней мере, с последней версией sqlite), но, кажется, работает безупречно, если вы используете что-то вроде delete from sqlite_master where type in ('table', 'index', 'trigger'). - person mlvljr; 19.10.2012
comment
Это также будет иметь побочный эффект в виде удаления таблицы android_metadata. В следующий раз, когда база данных будет открыта, эта таблица будет воссоздана, но чтобы воссоздать ее немедленно, вы можете изменить ведение журнала упреждающей записи или ограничения внешнего ключа на противоположное тому, как вы его настроили, а затем вернуть обратно. Это вызовет внутренний вызов reconfigure(), который запишет таблицу android_metadata. - person tophyr; 30.07.2015
comment
@ f470071 - просто добавьте его в предложение типа where - person Noah; 29.09.2015
comment
Согласно sqlite.org/fileformat2.html#sqlite_master, type также может быть триггером. Наверное, их тоже стоит удалить, я думаю. Но если вы удаляете все возможные типы в sqlite_master, вы можете просто delete без ограничения type. - person spaaarky21; 08.06.2016
comment
По крайней мере, для SQLite 3.12.2 эта таблица бросков sqlite_master не может быть изменена. - person rsaxvc; 16.07.2016

У меня была такая же проблема с SQLite и Android. Вот мое решение:

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);
}
person it-west.net    schedule 27.04.2013

Используя писклит:

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]))
person user3467349    schedule 16.11.2014

Я хотел бы добавить к другим ответам, связанным с удалением таблиц и без удаления файла, что вы также можете выполнить delete from sqlite_sequence для сброса последовательностей автоинкремента.

person Flavio Tordini    schedule 09.02.2012

Как только вы удалили все таблицы (и индексы исчезнут, когда таблица исчезнет), в базе данных SQLite, насколько я знаю, ничего не останется, хотя файл, похоже, не сжимается (из быстрого теста, который я только что сделал ).

Таким образом, удаление файла кажется самым быстрым - его нужно просто воссоздать, когда ваше приложение попытается получить доступ к файлу db.

person Mike Woodhouse    schedule 08.02.2009
comment
Файл не сжимается, потому что sqlite работает не так — он возвращает дисковое пространство ОС только в том случае, если вы очистите файл (по сути, воссоздаете его с нуля). До тех пор файл заполнен повторно используемым пространством. - person paxdiablo; 09.02.2009
comment
Ях. Таким образом, удаление всех таблиц и очистка имели бы смысл, если бы у вас не было прав на удаление/создание файлов или возникла какая-то странная многопользовательская ситуация. В противном случае просто удалить вещь? - person Mike Woodhouse; 09.02.2009

У меня была эта проблема в Android, и я написал метод, аналогичный этому - west.

Поскольку я использовал первичные ключи AUTOINCREMENT в своих таблицах, была таблица с именем sqlite_sequence. SQLite аварийно завершал работу, когда подпрограмма пыталась удалить эту таблицу. Я тоже не мог поймать исключение. Глядя на https://www.sqlite.org/fileformat.html#internal_schema_objects, Я узнал, что может быть несколько таких таблиц внутренней схемы, которые я не хочу удалять. В документации сказано, что имена всех этих таблиц начинаются с sqlite_, поэтому я написал этот метод

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();
    }
}
person Jon    schedule 31.08.2017

Не могу сказать, что это самое пуленепробиваемое или портативное решение, но для моих тестовых скриптов оно работает:

.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

Этот фрагмент кода перенаправляет вывод во временный файл, создает команды «удалить таблицу», которые я хочу запустить (отправляя команды во временный файл), устанавливает вывод обратно в стандартный вывод, затем выполняет команды из файла и, наконец, удаляет файл.

person Matt Malone    schedule 18.01.2018

Или в приглашении оболочки, всего в две строки, без именованного временного файла, предполагая, что $db — это имя базы данных SQLite:

echo "SELECT 'DROP TABLE ' || name ||';' FROM sqlite_master WHERE type = 'table';" |
    sqlite3 -readonly "$db" | sqlite3 "$db"
person peak    schedule 11.10.2019

Чтобы удалить также просмотры, добавьте ключевое слово «просмотр»:

delete from sqlite_master where type in ('view', 'table', 'index', 'trigger');
person Danilo Schembri    schedule 05.01.2021

person    schedule
comment
да, это удаляет базу данных, но в sqlite может быть что-то еще, кроме таблиц; Смотрите мой полный ответ для деталей - person Noah; 14.02.2009
comment
Если к базе данных открыто несколько подключений, это не сработает. На *nix это просто удалит имя, а соединения будут продолжать работать с безымянным файлом базы данных, пока не закроют свои дескрипторы. Если намерение состоит в том, чтобы переписать схему (удалить все таблицы, создать новые таблицы), у вас будут проблемы. - person jbarlow; 07.05.2011
comment
Это не должен быть принятый ответ, так как он удалил базу данных, которая включает в себя все хранимые процедуры, триггеры и т. д., а не только таблицы. - person Hobbyist; 13.01.2016
comment
Я считаю, что этот ответ действительно отвечает на вопрос, который плакат хотел задать: как мне легко начать с нуля с моей базой данных sqlite? Кто-то, вероятно, должен отредактировать вопрос, чтобы он был более ясным... если это возможно. - person Akrikos; 11.04.2017