【问题标题】:Room migration - how to alter ForeignKey's onDelete?房间迁移 - 如何更改 ForeignKey onDelete?
【发布时间】:2020-10-08 02:13:33
【问题描述】:

我在 Room 数据库中有一个 @Entity。它有 2 个外键,看起来像:

@Entity(
    tableName = "member_table",
    primaryKeys = ["member_chat_id", "member_user_id"],
    foreignKeys = [
        ForeignKey(
            entity = Chat::class,
            parentColumns = arrayOf("chat_id"),
            childColumns = arrayOf("member_chat_id"),
            onDelete = ForeignKey.NO_ACTION
        ),
        ForeignKey(
            entity = User::class,
            parentColumns = arrayOf("user_id"),
            childColumns = arrayOf("member_user_id"),
            onDelete = ForeignKey.NO_ACTION
        )
    ], indices = [
        Index(value = ["member_chat_id", "member_user_id"], unique = true)
    ]
)

现在,我需要将第一个外键更改为 onDelete = ForeignKey.CASCADE 以便删除此实体以及相应的 Chat::class 如何从onDelete = ForeignKey.NO_ACTION 迁移到onDelete = ForeignKey.CASCADE

【问题讨论】:

    标签: android kotlin android-room database-migration


    【解决方案1】:

    ALTER TABLE 的SQLite documentation 在标题为“进行其他类型的表架构更改”的部分中解释说,SQLite 直接支持的唯一架构更改命令是“重命名表”、“重命名列”和“添加列”。

    该文档还描述了进行其他架构更改所需的步骤,例如您需要进行的外键操作。基本概念是:

    1. 使用所需架构(“member_table_new”)创建一个新表
    2. 将现有表(“member_table”)中的数据复制到新表中
    3. 删除现有表
    4. 重命名新表,即“member_table_new”为“member_table”

    Room Sample 中的一个示例(在 Java 中)。

    对于您的更改,迁移类似于以下内容。如果member_table 有更多字段,请添加它们。还记得将迁移添加到您的database build statement

    // TODO Change version numbers as needed
    val MIGRATION_4_5 = object : Migration(4, 5) {
        override fun migrate(database: SupportSQLiteDatabase) {
            // Create the new table with "ON DELETE CASCADE" for member_chat_id foreign key action
            database.execSQL("""
                CREATE TABLE `member_table_new` (
                `member_chat_id` INTEGER NOT NULL,
                `member_user_id` INTEGER NOT NULL,
                PRIMARY KEY(`member_chat_id`, `member_user_id`),
                FOREIGN KEY(`member_chat_id`) REFERENCES `Chat`(`chat_id`) ON UPDATE NO ACTION ON DELETE CASCADE,
                FOREIGN KEY(`member_user_id`) REFERENCES `User`(`user_id`) ON UPDATE NO ACTION ON DELETE NO ACTION )"""
                .trimIndent())
    
            // Copy the rows from existing table to new table
            database.execSQL("""
                INSERT INTO member_table_new (member_chat_id, member_user_id)
                SELECT member_chat_id, member_user_id FROM member_table"""
                .trimIndent())
    
            // Remove the old table
            database.execSQL("DROP TABLE member_table");
            // Change the new table name to the correct one
            database.execSQL("ALTER TABLE member_table_new RENAME TO member_table");
    
        }
    }
    

    SQLite 文档说这些操作应该在事务中执行。 Room 在事务中执行迁移,因此您无需添加自己的迁移。

    在编写用于创建新表的 SQL 语句时,为表提供 Room 的架构会很有帮助。如果您还没有这样做,请将enable export of the schema information 写入 JSON 文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-26
      • 1970-01-01
      • 2019-02-18
      • 1970-01-01
      • 2020-05-17
      • 2019-02-13
      • 2018-02-20
      • 1970-01-01
      相关资源
      最近更新 更多