我在 Android 中有一個帶有 Room 的資料庫,我從中洗掉了一個列。我正在做遷移,我發現它并不像對已洗掉的列進行 DROP 那樣簡單。
然后我看到我必須采取一系列步驟,創建一個臨時表,該表稍后將成為帶有已洗掉列的新表,但問題是該表包含一個我不包含的字串陣列欄位知道如何在 SQL 中宣告。
@Entity(tableName = "recipe_table")
data class RecipesDb(
@PrimaryKey
@ColumnInfo(name = "id")
val id: Long,
@ColumnInfo(name = "name")
val name: String,
@ColumnInfo(name = "category")
val category: List<String>,
@ColumnInfo(name = "isRecommended")
val isRecommended: Boolean,
@ColumnInfo(name = "images")
val images: List<String>,
@ColumnInfo(name = "ingredients")
val ingredients: List<String>,
@ColumnInfo(name = "date")
val date: Long,
@ColumnInfo(name = "time")
val time: Int,
@ColumnInfo(name = "difficult")
val difficult: String,
@ColumnInfo(name = "originalUrl")
val originalURL: String? = null,
@ColumnInfo(name = "author")
val author: String,
@ColumnInfo(name = "siteName")
val siteName: String
)
現在我已經洗掉了該ingredients
列。我想做這樣的事情:
private val MIGRATION_3_2 = object : Migration(3,2) {
override fun migrate(database: SupportSQLiteDatabase) {
//Drop column isn't supported by SQLite, so the data must manually be moved
with(database) {
execSQL("CREATE TABLE Users_Backup (id INTEGER, name TEXT, PRIMARY KEY (id))")
execSQL("INSERT INTO Users_Backup SELECT id, name FROM Users")
execSQL("DROP TABLE Users")
execSQL("ALTER TABLE Users_Backup RENAME to Users")
}
}
}
但是當我宣告新的臨時表 User_Backup 時,我不知道如何指定其中一個欄位是陣列。最后,我能夠使用 Room 的 AutoMigrations 并創建一個界面來做到這一點,但我也想知道如何做到這一點。
uj5u.com熱心網友回復:
簡單的方法是使用@Database 注釋的物體串列中更改的@Entity 注釋類來編譯代碼(Ctrl F9)。
然后查看生成的 java(通過 Android Studio 中的 Android View 可見)。將有一個與 @Database 注釋類同名但后綴為_Impl的類。
在此類中,將有一個名為createAllTables的方法,其中包括 room 用于創建表的 SQL。
只需復制并粘貼適當的 SQL,然后更改表名,這不僅會使用正確的型別,還會應用 Room 期望的正確列約束。
我會建議
- 在創建表之前添加一個
execSQL("DROP TABLE IF EXISTS the_backup_table_name;")
(以防它已經存在) - 而不是使用
execSQL("DROP TABLE Users")
to 使用execSQL("DROP TABLE IF EXISTS the_original_table_name")
- 就個人而言,我總是重命名原始表名,然后重命名新表,最后 DROP 重命名的原始表。
我會使用:-
private val MIGRATION_3_2 = object : Migration(3,2) {
override fun migrate(database: SupportSQLiteDatabase) {
//Drop column isn't supported by SQLite, so the data must manually be moved
with(database) {
execSQL("DROP TABLE IF EXISTS Users_Backup")
execSQL("CREATE TABLE IF NOT EXISTS ....) //<<<<< SEE NOTES BELOW, the SQL MUST BE CHANGED.
execSQL("INSERT INTO Users_Backup SELECT id, name FROM Users")
execSQL("ALTER TABLE Users RENAME TO Old_Users")
execSQL("ALTER TABLE Users_Backup RENAME to Users")
execSQL("DROP TABLE IF EXISTS Old_users")
}
}
}
- note ....表示從生成的java復制SQL,表名由Users改為Users_Backup
- 第一行將洗掉 Uers_backup 以防萬一它碰巧存在,在例外情況下失敗的可能性要小一些。
- 而不是在將Users_Backup 重命名為Users之前洗掉Users表。第 4 個 execSQL 更改了Users表的名稱,因此如果將Users_Backup表更改為Users表時出現問題,則原始 Uers 表可作為 Old_users 使用。
- 完成所有操作后,將洗掉現在名為 Old_Users 的原始用戶表。
- 這些都只是更安全/安全一點。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/476325.html