【问题标题】:How to tell if sqlite database file is valid or not如何判断 sqlite 数据库文件是否有效
【发布时间】:2011-04-22 18:11:46
【问题描述】:

在下面的代码中,pathToNonDatabase 是一个简单文本文件的路径,而不是一个真正的 sqlite 数据库。我希望sqlite3_open 能够检测到这一点,但它没有(db 不是NULLresultSQLITE_OK)。那么,如何检测文件不是有效的sqlite数据库呢?

sqlite3 *db = NULL;
int result = sqlite3_open(pathToNonDatabase, &db);

if((NULL==db) || (result!=SQLITE_OK)) { 
   // invalid database
}

【问题讨论】:

    标签: database file sqlite detection


    【解决方案1】:

    sqlite 懒惰地打开数据库。只需在打开后立即执行一些要求它是数据库的操作。

    最好的可能是pragma schema_version;

    • 如果尚未创建数据库(例如,一个空文件),这将报告 0。在这种情况下,使用(并运行 CREATE TABLE 等)是安全的
    • 如果数据库已经创建,它将返回架构经历了多少次修订。这个值可能不有趣,但它不为零。
    • 如果文件存在且不是数据库(或为空),则会出现错误。

    如果您想要更彻底的检查,可以使用pragma quick_check;。这是一种轻量级的完整性检查,它跳过检查表的内容是否与索引对齐。它仍然可能很慢。

    避免integrity_check。它不仅会检查每一页,还会根据索引验证表的内容。这在大型数据库上是非常缓慢的。

    【讨论】:

    • "pragma schema_version;"有时会抛出“数据库已锁定”错误。我会给出“pragma quick_check;”试一试
    • 如果您的数据库被锁定,它就被锁定。一切都会失败。未锁定时重试。 :)
    • 你是对的。当数据库被锁定时,一切都会失败。甚至选择。就我而言,我想确定该文件是否是 Sqlite3 数据库。如果我收到“数据库已锁定”错误,我认为可以安全地假设该文件是 Sqlite3 数据库。
    • 这不适用于加密数据库(例如使用 SQLCipher)。
    • 不,它不会,除非你用同一个钥匙解锁它。这就是 SQLite 的设计方式,而 SQLCipher 就是对它的一种破解。
    【解决方案2】:

    对于需要在 C# 中使用 System.Data.SQLite 执行此操作的任何人,您可以启动一个事务,然后立即将其回滚,如下所示:-

        private bool DatabaseIsValid(string filename)
        {
            using (SQLiteConnection db = new SQLiteConnection(@"Data Source=" + filename + ";FailIfMissing=True;"))
            {
                try
                {
                    db.Open();
                    using (var transaction = db.BeginTransaction())
                    {
                        transaction.Rollback();
                    }
                }
                catch (Exception ex)
                {
                    log.Debug(ex.Message, ex);
                    return false;
                }
            }
            return true;
        }
    

    如果文件不是有效的数据库,则抛出以下SQLiteException - 文件已加密或不是数据库 (System.Data.SQLite.SQLiteErrorCode.NotADb)。如果您不使用加密数据库,那么这个解决方案就足够了。 (System.Data.SQLite 的 1.0.81.0 版只需要“db.Open()”,但是当我升级到 1.0.91.0 版时,我必须插入内部 using 块才能使其工作)。

    【讨论】:

      【解决方案3】:

      我认为编译指示完整性检查可以做到这一点。

      【讨论】:

      • 被警告;如果您的数据库很大,这可能会非常慢。
      【解决方案4】:

      如果您只想检查文件是否是有效的 sqlite 数据库,则可以使用此函数进行检查:

          private bool CheckIfValidSQLiteDatabase(string databaseFilePath)
          {
              byte[] bytes = new byte[16];
              using (FileStream fileStream = new FileStream(databaseFilePath, FileMode.Open, FileAccess.Read))
              {
                  fileStream.Read(bytes, 0, 16);
              }
              string gg = System.Text.ASCIIEncoding.ASCII.GetString(bytes);
              return gg.Contains("SQLite format");
          }
      

      如文档中所述: sqlite database header

      【讨论】:

        猜你喜欢
        • 2020-01-04
        • 2016-04-15
        • 1970-01-01
        • 1970-01-01
        • 2014-04-12
        • 1970-01-01
        • 1970-01-01
        • 2010-12-31
        • 1970-01-01
        相关资源
        最近更新 更多