【问题标题】:Drop all tables command删除所有表命令
【发布时间】:2010-10-06 05:55:19
【问题描述】:

在 SQLite 中删除所有表的命令是什么?

同样,我想删除所有索引。

【问题讨论】:

    标签: sql sqlite rdbms database


    【解决方案1】:

    虽然确实没有 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;
    

    【讨论】:

    • 如何在 onUpgrade() 中执行它们??
    • 直接执行DDL就够了
    • 如果由于某些疯狂的原因其他人有这个问题,上面的方法确实可以删除 Titanium Mobile 的数据库 API 中的所有表。
    • 非常聪明。我们自己的增量升级系统只能执行比较版本的脚本,这个技巧不需要任何改进:)
    • 注意:这可能会在 尝试清理数据库(至少使用最新的 sqlite)时出现奇怪的“数据库文件格式错误”问题,但似乎可以完美运行如果你使用类似delete from sqlite_master where type in ('table', 'index', 'trigger').
    【解决方案2】:

    我认为您不能一次删除所有表,但您可以执行以下操作来获取命令:

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

    这个输出是一个脚本,它将为您删除表格。对于索引,只需将表替换为索引即可。

    您可以使用where 部分中的其他子句来限制选择哪些表或索引(例如“and name glob 'pax_*'”用于以“pax_”开头的那些)。

    您可以将此脚本的创建与在一个简单的 bash(或 cmd.exe)脚本中运行它结合起来,这样只需运行一个命令。

    如果您不关心数据库中的任何信息,我认为您可以删除它存储在硬盘上的文件 - 这可能更快。我从未对此进行过测试,但我不明白为什么它不起作用。

    【讨论】:

    • 谢谢。很奇怪,没有简单的命令,而是这个 hacky SQL 查询。
    • 嗯,得到一个空的sqlite数据库最简单的方法就是删除文件,然后连接它..
    • 因此我的最后一段,@JF。
    • 附加到表的触发器会发生什么?
    • @rds,当你删除一个表时,它的所有触发器也会被删除。当触发器不可能触发时(因为表不再存在),保留触发器几乎没有意义。
    【解决方案3】:
    rm db/development.sqlite3
    

    【讨论】:

    • 是的,这确实删除了数据库,但是sqlite中除了表之外还可以有其他东西;有关详细信息,请参阅我的完整答案
    • 如果数据库打开了多个连接,这将不起作用。在只删除名称的 *nix 上,连接将继续使用未命名的数据库文件,直到它们关闭它们的句柄。如果意图是重写架构(删除所有表,创建新表),那么您将遇到麻烦。
    • 这不应该是公认的答案,因为它删除了数据库,其中包括所有存储过程、触发器等,而不仅仅是表。
    • 我相信这个答案确实回答了发帖人要问的问题:“我如何使用我的 sqlite 数据库轻松地从头开始?”有人可能应该将问题编辑得更清楚......如果可能的话。
    【解决方案4】:

    我在使用 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);
    }
    

    【讨论】:

      【解决方案5】:

      使用 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]))
      

      【讨论】:

        【解决方案6】:

        我想添加其他涉及删除表而不删除文件的答案,您也可以执行delete from sqlite_sequence 来重置自动增量序列。

        【讨论】:

          【解决方案7】:

          一旦你删除了所有的表(并且索引将在表消失时消失),据我所知,SQLite 数据库中没有任何内容,尽管文件似乎没有缩小(通过快速测试我已经做了)。

          因此删除文件似乎是最快的 - 当您的应用尝试访问 db 文件时应该重新创建它。

          【讨论】:

          • 文件不会缩小,因为这不是 sqlite 的工作方式 - 如果你清理文件(基本上从头开始重新创建它),它只会将磁盘空间返回给操作系统。在此之前,该文件已充满可重用空间。
          • 是的。因此,如果您没有文件删除/创建权限,或者存在一些奇怪的多用户情况,那么删除所有表并进行清理是有意义的。不然就删了?
          【解决方案8】:

          我在 Android 中遇到了这个问题,我写了一个类似于 it-west 的方法。

          因为我在表中使用了AUTOINCREMENT 主键,所以有一个名为sqlite_sequence 的表。当例程试图删除该表时,SQLite 会崩溃。我也无法捕捉到异常。查看https://www.sqlite.org/fileformat.html#internal_schema_objects,我了解到可能有几个我不想删除的internal schema 表。文档说这些表中的任何一个都有以 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();
              }
          }
          

          【讨论】:

            【解决方案9】:

            我不能说这是最防弹或最便携的解决方案,但它适用于我的测试脚本:

            .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”命令(将命令发送到临时文件),将输出设置回标准输出,然后执行文件中的命令,最后删除文件。

            【讨论】:

              【解决方案10】:

              或者在 shell 提示下,仅两行,没有命名的临时文件,假设 $db 是 SQLite 数据库名称:

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

              【讨论】:

                【解决方案11】:

                要删除视图,请添加“视图”关键字:

                delete from sqlite_master where type in ('view', 'table', 'index', 'trigger');
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2012-05-23
                  • 1970-01-01
                  • 2023-03-21
                  • 2022-11-16
                  • 2016-02-04
                  • 2021-05-25
                  • 2015-01-31
                  • 2012-03-06
                  相关资源
                  最近更新 更多