Android - Room如何在数据迁移中添加外键引用

6
我已经更新了我的Room实体,包括一个外键。现在我必须在数据迁移中包含此更改,但不确定SQL查询语句应该怎么写。
我尝试过以下方法,但它不能编译:
private val MIGRATION_1_2 = object: Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("ALTER TABLE `Entity` ADD FOREIGN KEY(`parent_id`) 
                REFERENCES `Entity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE)")
    }
}

你遇到了什么错误? - Itamar Kerbel
另外,我认为你有一个多余的括号。 - Itamar Kerbel
这里有一个类似的问题和答案 - Mahozad
1个回答

14

在SQLite中,添加外键无法通过修改表来实现,至少根据这个SQLite文档是不可能的:

只支持RENAME TABLEADD COLUMNRENAME COLUMN变体的ALTER TABLE命令。其他类型的ALTER TABLE操作,如DROP COLUMNALTER COLUMNADD CONSTRAINT等都被省略了。

考虑到这一点,我认为迁移数据库的正确方法应该是:

  1. 创建新的临时表,
  2. 将旧表中的值复制到临时表中,
  3. 删除旧表,
  4. 将临时表重命名为旧表名称。

在您的情况下,这可能看起来像这样:

override fun migrate(database: SupportSQLiteDatabase) {
    // Create a new translation table
    database.execSQL("CREATE TABLE IF NOT EXISTS `Entity_new` (" +
        "`old_column_1` TEXT NOT NULL, " +
        "`old_column_2` TEXT NOT NULL, " +
        "`parent_id` INTEGER, " +
        "`entity_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
        "FOREIGN KEY(`parent_id`) REFERENCES `Entity`(`entity_id`) ON UPDATE NO ACTION ON DELETE CASCADE )")
    // Copy the data
    database.execSQL("INSERT INTO `Entity_new` (old_column_1, old_column_2, entity_id) " +
        "SELECT old_column_1, old_column_2, entity_id " +
        "FROM Entity")
    // Remove old table
    database.execSQL("DROP TABLE Entity")
    // Change name of table to correct one
    database.execSQL("ALTER TABLE Entity_new RENAME TO Entity")
}

免责声明:本人采用了这个非常有用的PersistenceMigrationSample项目中的代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接