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


Ответы:


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.