You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Room Kotlin迁移跨库复制列值后数据库为空问题排查

问题分析与修复方案

1. SQL语法错误(核心问题)

你的两条UPDATE语句都缺少闭合括号,这会直接导致SQL执行失败,触发Room迁移的事务回滚,最终数据库可能被还原到迁移前状态,甚至出现空数据的情况。

  • 原迁移代码的UPDATE语句:
    UPDATE 'Catalogues' SET 'favorite' = (SELECT 'favorite' FROM 'fav' WHERE Catalogues.code = fav.itemCode
    
    正确写法需在末尾补充):
    UPDATE 'Catalogues' SET 'favorite' = (SELECT 'favorite' FROM 'fav'.FavoriteList WHERE Catalogues.code = fav.FavoriteList.itemCode)
    
  • 更新后的迁移代码的UPDATE语句同样存在该问题,修正后:
    UPDATE 'CatalogList' SET 'favorite' = (SELECT 'favorite' FROM fav.FavoriteList WHERE CatalogList.code = fav.FavoriteList.itemCode)
    

2. ATTACH语句的路径空格问题

更新后的代码中,$attachDbPath后多了一个空格:

database.execSQL("ATTACH DATABASE '$attachDbPath ' AS fav")

这会导致数据库路径解析错误,无法正确附加Favorite.db,后续查询自然拿不到数据。需去掉空格:

database.execSQL("ATTACH DATABASE '$attachDbPath' AS fav")

3. 数据库路径的空安全处理

database.path可能为null,直接拼接会引发空指针异常,需要做空安全校验:

val attachDbPath = database.path?.let { 
    File(it).parent?.plus(File.separator)?.plus("Favorite.db") 
} ?: throw IllegalStateException("无法获取数据库路径")

4. 无匹配数据时的默认值处理

如果CatalogList的code在FavoriteList中找不到对应itemCode,子查询会返回NULL,导致favorite列被设为NULL。若需要默认值(比如false或0),可以用COALESCE函数:

UPDATE 'CatalogList' SET 'favorite' = COALESCE((SELECT 'favorite' FROM fav.FavoriteList WHERE CatalogList.code = fav.FavoriteList.itemCode), 0)

5. 表名与列名的引号规范

SQLite中,单引号用于字符串值,表名/列名建议用反引号(`)或双引号包裹,避免语法歧义:

UPDATE `CatalogList` SET `favorite` = COALESCE((SELECT `favorite` FROM fav.`FavoriteList` WHERE `CatalogList`.`code` = fav.`FavoriteList`.`itemCode`), 0)

修正后的完整迁移代码

private val migration3To4 = object : Migration(3, 4) {
    override fun migrate(database: SupportSQLiteDatabase) {
        val attachDbPath = database.path?.let { 
            File(it).parent?.plus(File.separator)?.plus("Favorite.db") 
        } ?: throw IllegalStateException("无法获取数据库路径")

        database.execSQL("ATTACH DATABASE '$attachDbPath' AS fav")
        database.execSQL("""
            UPDATE `CatalogList` 
            SET `favorite` = COALESCE(
                (SELECT `favorite` FROM fav.`FavoriteList` WHERE `CatalogList`.`code` = fav.`FavoriteList`.`itemCode`), 
                0
            )
        """.trimIndent())
        database.execSQL("DETACH DATABASE fav")
    }
}

额外排查点

  • 确认Favorite.db路径正确:打印attachDbPath的值,检查是否与实际数据库文件路径一致。
  • 检查字段类型匹配:确保CatalogList.code和FavoriteList.itemCode的数据类型完全一致,否则匹配会失败。
  • 开启Room日志:在数据库构建器中添加日志配置,查看具体SQL执行错误:
    .setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
    

内容的提问来源于stack exchange,提问作者jane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:24:51