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


Ответы:


86

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

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

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

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

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

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


Благодарю. Очень странно, что нет простой команды, а вместо этого взломанный SQL-запрос.
— alamodey

7
Ну, самый простой способ получить пустую базу данных sqlite - просто удалить файл, а затем подключиться к нему ..
— Джон Фухи,

2
Отсюда мой последний абзац, @JF.
— paxdiablo

Что происходит с триггерами, прикрепленными к таблице?
— rds

@rds, когда вы удаляете таблицу, все триггеры для нее также удаляются. Нет смысла держать триггеры под рукой, если они не могут сработать (поскольку таблица больше не существует).
— paxdiablo

83

Хотя это правда, что нет команды 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;

1
как выполнить их в onUpgrade () ??
— AZ_

Просто выполните DDL, этого достаточно
— Ной

В случае, если по какой-то безумной причине у кого-то еще есть этот вопрос, вышеперечисленное помогает удалить все таблицы в API базы данных Titanium Mobile.
— Райли Даттон,

2
Невероятно умно. Наша самодельная система инкрементного обновления может выполнять только скрипты, сравнивая версии, этот трюк не требует никаких улучшений :)
— Иван Г.

3
ПРИМЕЧАНИЕ: это может вызвать странные проблемы «файл базы данных искажен» при второй попытке очистить базу данных (по крайней мере, с последним sqlite), но, похоже, работает безупречно, если вы используете что-то вроде delete from sqlite_master where type in ('table', 'index', 'trigger').
— mlvljr

36
rm db/development.sqlite3

да, это удаляет базу данных, но в sqlite может быть и другое, кроме таблиц; Подробности см. В моем полном ответе
— Ной

9
Если в базе данных открыто несколько подключений, это не сработает. На * nix, который просто удалит имя, и соединения будут продолжать работать с безымянным файлом базы данных, пока они не закроют свои дескрипторы. Если намерение состоит в том, чтобы переписать схему (отбросить все таблицы, создать новые таблицы), тогда у вас будут проблемы.
— jbarlow

3
Это не должен быть принятым ответом, поскольку он удалил базу данных, которая включает в себя все хранимые процедуры, триггеры и т. Д., А не только таблицы.
— Hobbyist

2
Я считаю, что этот ответ действительно отвечает на вопрос, который хотел задать плакат: «Как мне легко начать с нуля с моей базой данных sqlite?» Кто-то, наверное, должен отредактировать вопрос, чтобы он был более ясным ... если это возможно.
— Akrikos

22

У меня была такая же проблема с 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);
}

4

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


4

Используя 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]))

3

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

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


1
Файл не сжимается, потому что sqlite не работает - он вернет дисковое пространство ОС только в том случае, если вы очистите файл (в основном воссоздаете его с нуля). А пока в файле много места для повторного использования.
— paxdiablo

Ага. Таким образом, удаление всех таблиц и очистка имеет смысл, если у вас нет прав на удаление / создание файлов или возникла какая-то странная многопользовательская ситуация. Иначе просто удалить вещь?
— Майк Вудхаус,

2

У меня была эта проблема в Android, и я написал метод, похожий на it-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();
    }
}

1

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

.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

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


0

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

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

0

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

delete from sqlite_master where type in ('view', 'table', 'index', 'trigger');
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.