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

Android Room修改复合主键的迁移:处理字段复制冲突

Android Room 迁移:处理字段复制与主键冲突删除

要实现将tranAmt值复制到amount字段,并在出现主键冲突时删除amount为空的记录,你可以通过Room的Migration类执行以下两步SQL操作:

步骤1:删除会引发冲突的空amount记录

先清理那些在更新后会和现有记录主键重复的条目——即存在同tranParticular、同tranId且amount等于当前记录tranAmt的情况下,删除amount为空的那条记录:

DELETE FROM statements
WHERE amount IS NULL
AND EXISTS (
    SELECT 1 FROM statements s2
    WHERE s2.tranParticular = statements.tranParticular
    AND s2.tranId = statements.tranId
    AND s2.amount = statements.tranAmt
)

步骤2:将剩余空amount记录的字段值替换为tranAmt

完成冲突记录清理后,把所有剩余amount为空的记录的amount字段更新为tranAmt的值:

UPDATE statements
SET amount = tranAmt
WHERE amount IS NULL

整合到Room迁移类中

将上述SQL语句封装到Room的Migration实现里,对应数据库版本升级:

// 替换x和x+1为实际的数据库版本号,比如从版本3升级到4
val MIGRATION_3_TO_4 = object : Migration(3, 4) {
    override fun migrate(database: SupportSQLiteDatabase) {
        // 执行冲突记录删除
        database.execSQL("""
            DELETE FROM statements
            WHERE amount IS NULL
            AND EXISTS (
                SELECT 1 FROM statements s2
                WHERE s2.tranParticular = statements.tranParticular
                AND s2.tranId = statements.tranId
                AND s2.amount = statements.tranAmt
            )
        """)
        // 执行字段更新
        database.execSQL("""
            UPDATE statements
            SET amount = tranAmt
            WHERE amount IS NULL
        """)
    }
}

最后别忘了在Room数据库实例化时添加这个迁移规则:

Room.databaseBuilder(context, AppDatabase::class.java, "your-db-name")
    .addMigrations(MIGRATION_3_TO_4)
    .build()

注意事项

  • 务必确保版本号与数据库当前版本和目标版本匹配
  • 建议在测试环境验证迁移逻辑,避免数据丢失
  • 如果tranAmt存在为空的场景,需额外添加判断逻辑避免无效更新

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 02:20:54