android-Room如何为数据迁移添加外键参考

时间:2019-05-30 08:57:30

标签: android sql android-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)")
     }
}

1 个答案:

答案 0 :(得分:4)

对于您来说可能为时已晚,但对于任何在这里看过的人来说:

在SQLite上,至少根据以下sqlite documentation,不可能更改表以添加外键: “仅支持ALTER TABLE命令的RENAME TABLE,ADD COLUMN和RENAME COLUMN变体。其他种类的ALTER TABLE操作,例如DROP COLUMN,ALTER COLUMN,ADD 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 project中的代码。