android - 如何为使用 Room Auto-Migrations 创建的新列设置现有行的默认值?

标签 android sql kotlin android-room database-migration

我有一个包含几列的 Room SQL 表。我想再添加一个包含 bool 值的列。为了将我的数据库迁移到这个新模式,我正在尝试使用 Room Auto-Migrations .我的问题是如何更新表中现有的行以具有值 false对于这个新添加的列?我是否必须通过更改表并将默认值插入所有行来回退到编写手动迁移?

最佳答案

My question is how can I update my existing rows in the table to have a value false for this newly added column?


使用 @ColumnInfo默认值 例如对于实体中的列。
@ColumnInfo(defaultValue = "0") 

Will I have to fallback to writing manual migration by altering the table and inserting the default value to all rows?


这应该在自动迁移时添加具有默认值子句的列。
  • 我相信(如果没有记错的话)如果您不编写默认值,那么由于新列没有默认值,自动迁移将失败。

  • 附加
    如果您想使用默认值插入,您将无法使用便利 @Insert使用@Dao 注释但必须使用@Query 的相应接口(interface)/抽象类中的注释列出的列省略了要使用默认值的列,并且具有指定命名列的值的 VALUES 子句。
    例如对于具有 3 列的表,columa、columnb 和 columnc;其中 columnc 指定了 DEFAULT,那么插入函数可能类似于:-
    @Query("INSERT INTO the_table (columna,columnb) VALUES(:valueForColumnA,:valueForColumnB);")
    fun insertWithDefaultValueForColumnC(valueForColumnA: TheType,valueForColumnB: TheType): Long
    
  • 注意以上是原则代码,它没有被编译、测试或运行,所以可能包含一些错误。

  • 补充评论

    I tried @ColumnInfo(defaultValue = "1") and @ColumnInfo(defaultValue = "true") to set the default value to true. But that didn't work.


    defaultValue = "1"defaultvalue = "0"做工作 (1 为真,0 为假)。
    然而 , default = "false"default = "true" 不要按预期工作 .他们会得到与 default = "whatever...." 相似的结果。 .
    也许是一个错误,也许是 Room 的问题。后者发生的情况是它们作为字符串(SQLite 中的 TEXT)传递,因此即使列已定义为 bool 值,它们实际上也是如此插入的。 SQLite 允许这样的值是因为任何列都可以存储任何类型的灵 active 。
    考虑以下实体:-
    @Entity
    data class Example1(
        @PrimaryKey
        val id: Long? = null,
        val name: String,
        /*
         ADDITIONS FOR V2
         */
        @ColumnInfo(defaultValue = "1")
        val b1: Boolean,
        @ColumnInfo(defaultValue = "0")
        val b2: Boolean,
        @ColumnInfo(defaultValue = "false")
        val b3: Boolean,
        @ColumnInfo(defaultValue = "true")
        val b4: Boolean
    )
    
  • 添加 b1-b4 并在运行版本 1 时存在 10 行时完成自动迁移,并且在运行版本 2 时运行另外 10 行并添加另外 10 列,如下所示:-
      db = TheDatabase.getInstance(this)
      dao = db.getAllDao()
      for (i in 1..10) {
          dao.insert(Example1(name = "V${DATABASE_VERSION}_$i", b1 = true, b2 = true, b3 = true, b4 = true))
      }
    
      for(e: Example1 in dao.getAllExample1s()) {
          Log.d("DBINFO","Name is ${e.name} id id ${e.id} " +
          /*" ADDED COL = There Aren't any" */
          " B1=${e.b1} B2=${e.b2} B3=${e.b3} B4=${e.b4}"
          )
      }
    

  • 第二次运行的结果是:-
    2022-01-05 09:41:43.503 D/DBINFO: Name is V1_1 id id 1  B1=true B2=false B3=false B4=false
    2022-01-05 09:41:43.504 D/DBINFO: Name is V1_2 id id 2  B1=true B2=false B3=false B4=false
    2022-01-05 09:41:43.504 D/DBINFO: Name is V1_3 id id 3  B1=true B2=false B3=false B4=false
    2022-01-05 09:41:43.504 D/DBINFO: Name is V1_4 id id 4  B1=true B2=false B3=false B4=false
    2022-01-05 09:41:43.504 D/DBINFO: Name is V1_5 id id 5  B1=true B2=false B3=false B4=false
    2022-01-05 09:41:43.504 D/DBINFO: Name is V1_6 id id 6  B1=true B2=false B3=false B4=false
    2022-01-05 09:41:43.504 D/DBINFO: Name is V1_7 id id 7  B1=true B2=false B3=false B4=false
    2022-01-05 09:41:43.504 D/DBINFO: Name is V1_8 id id 8  B1=true B2=false B3=false B4=false
    2022-01-05 09:41:43.504 D/DBINFO: Name is V1_9 id id 9  B1=true B2=false B3=false B4=false
    2022-01-05 09:41:43.504 D/DBINFO: Name is V1_10 id id 10  B1=true B2=false B3=false B4=false
    2022-01-05 09:41:43.504 D/DBINFO: Name is V2_1 id id 11  B1=true B2=true B3=true B4=true
    2022-01-05 09:41:43.504 D/DBINFO: Name is V2_2 id id 12  B1=true B2=true B3=true B4=true
    2022-01-05 09:41:43.505 D/DBINFO: Name is V2_3 id id 13  B1=true B2=true B3=true B4=true
    2022-01-05 09:41:43.505 D/DBINFO: Name is V2_4 id id 14  B1=true B2=true B3=true B4=true
    2022-01-05 09:41:43.505 D/DBINFO: Name is V2_5 id id 15  B1=true B2=true B3=true B4=true
    2022-01-05 09:41:43.505 D/DBINFO: Name is V2_6 id id 16  B1=true B2=true B3=true B4=true
    2022-01-05 09:41:43.505 D/DBINFO: Name is V2_7 id id 17  B1=true B2=true B3=true B4=true
    2022-01-05 09:41:43.505 D/DBINFO: Name is V2_8 id id 18  B1=true B2=true B3=true B4=true
    2022-01-05 09:41:43.506 D/DBINFO: Name is V2_9 id id 19  B1=true B2=true B3=true B4=true
    2022-01-05 09:41:43.506 D/DBINFO: Name is V2_10 id id 20  B1=true B2=true B3=true B4=true
    
    前 10 行已按以下方式应用默认值:-
  • 根据编码的默认值,b1 为真,即 1 = true
  • 根据编码的默认值,b2 为 false,即 0 = false
  • b3 和 b4 为假,因为该值是无法转换为 Int 的 TEXT/STRING(如下所示),因此它不会发生异常,而是将其转换为 0,因此为假。

  • 如果 应用检查 用于查看它显示的数据:-
    enter image description here
    如果再次使用 应用检查/数据库检查员 以及使用 SELECT *,typeof(b1),typeof(b2),typeof(b3),typeof(b4) FROM example1; 查询的表然后 :-
    enter image description here
    即自动迁移之前存在的 10 行的 b3 和 b4 列保存为 TEXT。

    关于android - 如何为使用 Room Auto-Migrations 创建的新列设置现有行的默认值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70574648/

    相关文章:

    sql - 将三个查询合并为一个结果

    sql - 查询显示表之间不匹配的记录

    sql - Postgres 数据操作

    android - 当自定义 View 不是为处理点击而设计时,如何处理自定义 View 中的可访问性?

    android - invokedynamic 需要 --min-sdk-version >= 26

    弹出对话框更新数据库后的Android更新Mainactivity ListView

    android - 仅获取我的 Android 应用程序附带的区域设置列表

    android - 如何设计一个在后台对网页进行测试,让用户正常使用手机的APP?

    java - 如何创建mp3文件的缩略图

    java - Kotlin 术语 "mutable"错了吗?