Android Room数据迁移:添加外键引用的SQL语句编译失败问题咨询
解决Room迁移中添加外键的问题
你遇到的问题其实挺常见的——SQLite 本身不支持通过 ALTER TABLE 直接添加外键约束,这就是你的代码编译失败的核心原因。要在现有表中添加外键,我们得通过创建临时表、迁移数据、替换原表的方式来实现,具体步骤和代码如下:
正确的迁移逻辑
- 创建一个和原表结构一致,但包含外键约束的临时表
- 将原表中的所有数据迁移到临时表中
- 删除原来的旧表
- 把临时表重命名为原表的名字
完整的迁移代码示例
针对你的Entity表(假设原表已有id主键字段,现在要新增parent_id字段并添加外键关联自身的id),正确的迁移代码应该是这样的:
private val MIGRATION_1_2 = object : Migration(1, 2) { override fun migrate(database: SupportSQLiteDatabase) { // 1. 创建包含外键约束的临时表,要完整复制原表的所有字段 database.execSQL(""" CREATE TABLE `Entity_temp` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, -- 这里要列出原表的所有其他字段,比如原表有`name` TEXT NOT NULL就加上对应的行 `parent_id` INTEGER, FOREIGN KEY(`parent_id`) REFERENCES `Entity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE ) """) // 2. 将原表数据迁移到临时表,字段要和临时表对应 database.execSQL(""" INSERT INTO `Entity_temp` (`id`, `parent_id`/*, 原表其他字段*/) SELECT `id`, NULL /*原表无parent_id,用NULL填充*/ /*, 原表其他字段*/ FROM `Entity` """) // 3. 删除原表 database.execSQL("DROP TABLE `Entity`") // 4. 重命名临时表为原表名 database.execSQL("ALTER TABLE `Entity_temp` RENAME TO `Entity`") } }
重要注意事项
- 一定要完整复制原表的所有字段到临时表,遗漏任何字段都会导致对应数据丢失
- 如果原表有索引、唯一约束等额外规则,也要在临时表中同步创建
- 迁移数据时,字段顺序要和临时表完全匹配;如果
parent_id不允许为空,需要根据业务逻辑填充默认值而非NULL - 注意反引号的使用,避免表名、字段名和SQL关键字冲突
内容的提问来源于stack exchange,提问作者David Jarvis
相关产品推荐
相关产品推荐

