android.database.sqlite.SQLiteException:没有这样的表:国家(代码 1 SQLITE_ERROR)

Posted

技术标签:

【中文标题】android.database.sqlite.SQLiteException:没有这样的表:国家(代码 1 SQLITE_ERROR)【英文标题】:android.database.sqlite.SQLiteException: no such table: countries (code 1 SQLITE_ERROR) 【发布时间】:2021-08-24 05:17:37 【问题描述】:

我刚刚在我的项目中实现了 SQLite 数据库,该应用程序在旧应用程序中运行良好,但是在我将数据库文件传输到另一个应用程序并尝试运行它之后,它给了我这个错误

android.database.sqlite.SQLiteException: no such table: countries (code 1 SQLITE_ERROR): , while compiling: SELECT * FROM countries

现在我尝试运行运行良好的旧应用程序,但现在它也无法运行并给出相同的错误。

我对此进行了很多搜索并尝试以这些方式解决错误,但对我没有任何帮助

清除数据,重新安装应用... 正在更改数据库的版本和名称... 在 onOpen 中调用 onCreate...

还有一些类似的,但没有任何技巧可以工作

这是我的整个数据库助手类(修改后)

class LocationDB(private val myContext: Context) 
    private var dbPath: String? = null
    private var db: SQLiteDatabase? = null
    private var dbHelper: DatabaseHelper

    inner class DatabaseHelper
        (context: Context?) : SQLiteOpenHelper(context, DB_NAME, null, 5) 
        override fun onCreate(db: SQLiteDatabase) 

        override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) 
            if(newVersion>oldVersion)
                copyDataBase()
        

        override fun onOpen(db: SQLiteDatabase?) 
            if (db != null) 
                onCreate(db)
            
        
    

    @Throws(IOException::class)
    fun createDataBase() 
        val dbExist = checkDataBase()
        if (!dbExist) 
            dbHelper.readableDatabase
            try 
                copyDataBase()
             catch (e: IOException) 
                throw Error("Error copying database")
            
        
    

    private fun checkDataBase(): Boolean 
        var checkDB: SQLiteDatabase? = null
        try 
            val myPath = dbPath + DB_NAME
            checkDB = SQLiteDatabase.openDatabase(
                myPath, null,
                SQLiteDatabase.OPEN_READONLY
            )
         catch (e: SQLiteException) 
        
        checkDB?.close()
        return checkDB != null
    

    @Throws(IOException::class)
    private fun copyDataBase() 
        val myInput = myContext.assets.open(DB_NAME)

        val outFileName = dbPath + DB_NAME

        val myOutput: OutputStream = FileOutputStream(outFileName)

        val buffer = ByteArray(1024)
        var length: Int
        while (myInput.read(buffer).also  length = it  > 0) 
            myOutput.write(buffer, 0, length)
        

        myOutput.flush()
        myOutput.close()
        myInput.close()
    

    @Throws(SQLException::class)
    fun openDB(): LocationDB 
        db = dbHelper.writableDatabase
        return this
    

    fun closeDB() 
        dbHelper.close()
    

    val countries: Cursor?
        get() 
            val query = "SELECT * FROM countries"
            return db?.rawQuery(query, null)
        

    fun getStateAsPerCountry(country_id: String): Cursor? 
        val query = "SELECT * FROM states where country_id=$country_id"
        return db?.rawQuery(query, null)
    

    fun getCitiesAsPerState(state_id: String): Cursor? 
        val query = "SELECT * FROM cities where state_id=$state_id"
        return db?.rawQuery(query, null)
    

    companion object 
        const val DB_NAME = "Location.db"
    

    init 
        dbPath = myContext.filesDir.path + myContext.packageName + "/databases/"
        dbHelper = DatabaseHelper(myContext)
    

已编辑(2021 年 10 月 6 日)

我看到 设备文件资源管理器,我知道数据库的路径默认是 /data/data/com.my.package/databases/Location.db。当我在错误断点处调试应用程序时,我看到路径不同,或者我们可以说数据库助手正在从不同的路径 /data/user/0/com.my.package/databases/Location 获取数据库。 db 不存在,因此很明显,如果没有确切的路径,表将始终为空或未创建。但问题是我们为什么以及如何初始化正确的路径。

为此,我这样做并获得了确切的路径,但它仍然无法正常工作

val countries: Cursor?
        get() 
            db = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY) 
            val query = "SELECT * FROM countries"
            return db?.rawQuery(query, null)
         

这是数据库的图片

【问题讨论】:

Here你可能会发现一些提示 为什么你的 onCreate() 方法是空的。 ? 【参考方案1】:

据我了解您的问题,我认为您共享的数据助手类没有任何问题。看起来很完美。我可以看到Location.db 中有国家表,正如你所说,数据库放置在正确的路径中,但数据库没有表,这意味着它应该是空的。

所以问题在于您使用数据库的那个类,因为正在创建虚拟数据库,但它没有从您现成的Location.db 中获取数据,这意味着它没有为此创建打电话

db.createDataBase()

在调用该类的 onCreate 中的国家/地区等其他函数之前。

【讨论】:

【参考方案2】:

检查您的数据库检查器以了解表“国家”是否真的存在。

如果不是,您需要在数据库助手中重新创建它。

【讨论】:

我无法在数据库检查器中获取它。它显示为 Location.db (Closed),而且我认为不能更改表名,因为正如我提到的,数据库在旧应用程序中运行良好。 如果数据库关闭,你将无法访问你的数据库,这意味着你的数据库没有正确连接,难怪你的表没有显示出来。要解决这个问题,也许您可​​以尝试执行 File -> Invalidate Caches / Restart【参考方案3】:

确保表名countries 与查询中的表名拼写相同。

Update

尝试将路径硬编码为

dbPath = "/data/data/com.my.package/databases/"+DB_NAME 

【讨论】:

我无法在数据库检查器中获取它。它显示为 Location.db (Closed),而且我认为不能更改表名,因为正如我提到的,数据库在旧应用程序中运行良好。 有时会出现拼写错误。您可以尝试从 View > Tool Windows > Device File Explorer 进入 Android Studio 中的 db 位置,以检查 db 是否正确复制到您指定的路径。 我看到路径正确为“/data/data/com.my.package/databases/”【参考方案4】:

通常数据库存储在context.getDatabasePath(name) 下。此功能的优点是系统确保选择正确的路径而不是硬编码。

当您的设备连接到 Android Studio 时,您可以在您的 Device File Explorer 中查看设备上存储了哪些文件,甚至可以访问您的应用程序的沙箱,在其中可以找到数据库。您可以在那里下载沙盒中的文件并在您的计算机上本地打开它。

如果数据库配置正确,您甚至可以使用Database Inspector

在调试代码时,您可能会发现数据库复制错误的位置导致数据库没有您正在查询的表。

【讨论】:

我已经检查了文件资源管理器它在正确的路径中【参考方案5】:

“当我调试查询时,变量 db 返回“/data/user/0/com.my.package/databases/Location.db”,而 dbPath 是“/data/data/com.my.package/databases /”这意味着您的查询检查数据库在“用户”文件夹下而不是数据文件夹下。 这就是你得到 android.database.sqlite.SQLiteException: no such table: countries 的原因。

要检查国家/地区表是否在您的应用中,请打开查看->工具窗口->设备文件资源管理器

在数据文件夹下找到“/data/data/com.my.package/databases/Location.db”

使用SQLLiteDatabaseBrowserPortable检查Location db下的表。如果Location.db不在数据库下,则可以使用SQLLiteDatabaseBrowserPortable手动创建新的db和表。

然后,将 db 路径更改为“/data/data/com.my.package/databases/Location.db”

然后运行你的程序。希望可以工作。

【讨论】:

我已经在数据库浏览器和设备中检查了表格,一切都很完美。

以上是关于android.database.sqlite.SQLiteException:没有这样的表:国家(代码 1 SQLITE_ERROR)的主要内容,如果未能解决你的问题,请参考以下文章