Kotlin,预打包数据库有一个无效的模式:列顺序错误?
Kotlin, Pre-packaged database has an invalid schema: Column order is wrong?
我从模拟器导出了数据库的副本,并将测试数据库移动到外部文件。这一段时间以来一直运行良好,但是,今天发生了一些变化,出现了这个错误。
预打包的数据库有一个无效的模式:tableLinkUserToPassword
预计:
TableInfo
{
name='tableLinkUserToPassword',
columns = {
userId = Column { name='userId', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null' },
password = Column { name='password', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null' }
},
foreignKeys = [ForeignKey
{
referenceTable='tableUser', onDelete='CASCADE', onUpdate='NO ACTION', columnNames=[userId], referenceColumnNames=[userId]
}
],
indices = [Index { name='index_tableLinkUserToPassword_password', unique=false, columns=[password], orders=[ASC] },
Index { name='index_tableLinkUserToPassword_userId', unique=false, columns=[userId], orders=[ASC]}
]
}
找到:
TableInfo{name='tableLinkUserToPassword', columns={password=Column{name='password', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, userId=Column{name='userId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}}, foreignKeys=[ForeignKey{referenceTable='tableUser', onDelete='CASCADE', onUpdate='NO ACTION', columnNames=[userId], referenceColumnNames=[userId]}], indices=[Index{name='index_tableLinkUserToPassword_userId', unique=false, columns=[userId], orders=[ASC]}, Index{name='index_tableLinkUserToPassword_password', unique=false, columns=[password], orders=[ASC]}]}
UserId
和 Password
列顺序交换。和notNull=false
好像不匹配。
我有 DB Browser,但我该如何更改顺序或列?
实体:
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
@Entity(
tableName = "tableLinkUserToPassword",
foreignKeys = [
ForeignKey(
entity = EntityUser::class,
parentColumns = ["userId"],
childColumns = ["userId"],
onDelete = ForeignKey.CASCADE
)
]
)
data class EntityLinkUserToPassword(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(index = true)
val userId: Int,
val password: String,
)
感谢您的帮助
列出现的顺序不是问题,而是提取它们的顺序(我认为)。重要的是报告的值。
但是,可以看出,举个例子,就是密码 EXPECTED 列(从注释为 class 的 @Entity 中提取的内容)具有 NOT NULL
约束(即它不能为空)根据 notNull=true
,同时它发现 FOUND 中的密码列没有编码的 NOT NULL 约束(即 pre-packaged 数据库)根据 notNull=false
.
所以您要么必须更改 EntityLinkUserToPassword class 以允许空值,要么更改 pre-packaged 数据库以在密码列上编码为 NOT NULL .
例如val password: String?,
您需要检查所有列中发现的和预期的差异。
P.S。 userId 列上的第二个索引既浪费又低效。 PrimaryKey 是一个索引。所以不需要 @ColumnInfo
注释。
但是,pre-packaged 数据库的第二个索引又出现在密码列上。所以你应该移动 @ColumnInfo
注释以应用于密码 val/column 例如我相信你想要:-
data class EntityLinkUserToPassword(
@PrimaryKey(autoGenerate = true)
val userId: Int,
@ColumnInfo(index = true)
val password: String?,
)
- 注意以上为观察所得,建议代码未经测试不一定全面,可能有遗漏或错误。
I have DB Broswer but how would I chnage the order or columns?
你would/could:-
- 重命名 EntityLinkUserToPassword table 例如
ALTER TABLE EntityLinkUserToPassword RENAME TO renamed_EntityLinkUserToPassword;
- 使用
UPDATE renamed_EntityLinkUserToPassword SET password = 'a suitable default value' WHERE password IS NULL;
- 这样您在复制数据时就不会遇到 NOT NULL 约束冲突。
- 使用正确的架构创建新的 table(见下文)
- 使用
INSERT INTO EntityLinkUserToPassword SELECT * FROM renamed_EntityLinkUserToPassword ORDER BY userId ASC;
DROP TABLE IF EXISTS renamed_EntityLinkUserToPassword'
获取正确的架构
- 使用 @Entity 注释的 classes 根据需要编码并在 @Database 注释的实体参数中定义,编译项目。
- 使用 Android View in Android Studio 查看 Java(generated) for a class same名称作为 @Database 注释 class 但后缀为 _Impl.
- 寻找
createAllTables
方法。用于创建 table 的 SQL 是硬编码的。复制它,这将是精确的 SQL.
我从模拟器导出了数据库的副本,并将测试数据库移动到外部文件。这一段时间以来一直运行良好,但是,今天发生了一些变化,出现了这个错误。
预打包的数据库有一个无效的模式:tableLinkUserToPassword
预计:
TableInfo
{
name='tableLinkUserToPassword',
columns = {
userId = Column { name='userId', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null' },
password = Column { name='password', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null' }
},
foreignKeys = [ForeignKey
{
referenceTable='tableUser', onDelete='CASCADE', onUpdate='NO ACTION', columnNames=[userId], referenceColumnNames=[userId]
}
],
indices = [Index { name='index_tableLinkUserToPassword_password', unique=false, columns=[password], orders=[ASC] },
Index { name='index_tableLinkUserToPassword_userId', unique=false, columns=[userId], orders=[ASC]}
]
}
找到:
TableInfo{name='tableLinkUserToPassword', columns={password=Column{name='password', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, userId=Column{name='userId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}}, foreignKeys=[ForeignKey{referenceTable='tableUser', onDelete='CASCADE', onUpdate='NO ACTION', columnNames=[userId], referenceColumnNames=[userId]}], indices=[Index{name='index_tableLinkUserToPassword_userId', unique=false, columns=[userId], orders=[ASC]}, Index{name='index_tableLinkUserToPassword_password', unique=false, columns=[password], orders=[ASC]}]}
UserId
和 Password
列顺序交换。和notNull=false
好像不匹配。
我有 DB Browser,但我该如何更改顺序或列?
实体:
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
@Entity(
tableName = "tableLinkUserToPassword",
foreignKeys = [
ForeignKey(
entity = EntityUser::class,
parentColumns = ["userId"],
childColumns = ["userId"],
onDelete = ForeignKey.CASCADE
)
]
)
data class EntityLinkUserToPassword(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(index = true)
val userId: Int,
val password: String,
)
感谢您的帮助
列出现的顺序不是问题,而是提取它们的顺序(我认为)。重要的是报告的值。
但是,可以看出,举个例子,就是密码 EXPECTED 列(从注释为 class 的 @Entity 中提取的内容)具有 NOT NULL
约束(即它不能为空)根据 notNull=true
,同时它发现 FOUND 中的密码列没有编码的 NOT NULL 约束(即 pre-packaged 数据库)根据 notNull=false
.
所以您要么必须更改 EntityLinkUserToPassword class 以允许空值,要么更改 pre-packaged 数据库以在密码列上编码为 NOT NULL .
例如val password: String?,
您需要检查所有列中发现的和预期的差异。
P.S。 userId 列上的第二个索引既浪费又低效。 PrimaryKey 是一个索引。所以不需要 @ColumnInfo
注释。
但是,pre-packaged 数据库的第二个索引又出现在密码列上。所以你应该移动 @ColumnInfo
注释以应用于密码 val/column 例如我相信你想要:-
data class EntityLinkUserToPassword(
@PrimaryKey(autoGenerate = true)
val userId: Int,
@ColumnInfo(index = true)
val password: String?,
)
- 注意以上为观察所得,建议代码未经测试不一定全面,可能有遗漏或错误。
I have DB Broswer but how would I chnage the order or columns?
你would/could:-
- 重命名 EntityLinkUserToPassword table 例如
ALTER TABLE EntityLinkUserToPassword RENAME TO renamed_EntityLinkUserToPassword;
- 使用
UPDATE renamed_EntityLinkUserToPassword SET password = 'a suitable default value' WHERE password IS NULL;
- 这样您在复制数据时就不会遇到 NOT NULL 约束冲突。
- 使用正确的架构创建新的 table(见下文)
- 使用
INSERT INTO EntityLinkUserToPassword SELECT * FROM renamed_EntityLinkUserToPassword ORDER BY userId ASC;
DROP TABLE IF EXISTS renamed_EntityLinkUserToPassword'
获取正确的架构
- 使用 @Entity 注释的 classes 根据需要编码并在 @Database 注释的实体参数中定义,编译项目。
- 使用 Android View in Android Studio 查看 Java(generated) for a class same名称作为 @Database 注释 class 但后缀为 _Impl.
- 寻找
createAllTables
方法。用于创建 table 的 SQL 是硬编码的。复制它,这将是精确的 SQL.