我正在尝试更新会议室数据库 想要在现有数据库中添加两列,并且不想丢失数据。
我现有的表名WordTable
@Entity
data class WordTable(
@PrimaryKey(autoGenerate = true)
var id: Int = 0,
var word: String = "",
var des: String = "",
var bookmark: Boolean = false,
var addByUser: Boolean = false,
var uploaded: Boolean = false)
我想添加这两列,所以我的代码现在是
@Entity
data class WordTable(
@PrimaryKey(autoGenerate = true)
var id: Int = 0,
var word: String = "",
var des: String = "",
var ref: String = "Added by user",
var recent: Date = Date(),
var bookmark: Boolean = false,
var addByUser: Boolean = false,
var uploaded: Boolean = false)
注意:我提供日期换算器
创建一个新表
database.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT," +
" word TEXT," +
" des TEXT," +
" ref TEXT," +
" recent INTEGER," +
" bookmark INTEGER," +
" addByUser INTEGER," +
" uploaded INTEGER)")
复制以前的数据
database.execSQL("Insert Into USER (id, word, des, bookmark, addByUser, uploaded) Select * From WordTable")
删除单词表
database.execSQL("Drop Table WordTable")
将用户表重命名为WordTable
database.execSQL("Alter Table USER RENAME TO WordTable")
我得到这个错误;
Expected:
TableInfo{name='WordTable', columns={addByUser=Column{name='addByUser', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, word=Column{name='word', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, bookmark=Column{name='bookmark', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, uploaded=Column{name='uploaded', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1}, ref=Column{name='ref', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, des=Column{name='des', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, recent=Column{name='recent', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='WordTable', columns={addByUser=Column{name='addByUser', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0}, word=Column{name='word', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, bookmark=Column{name='bookmark', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0}, uploaded=Column{name='uploaded', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1}, ref=Column{name='ref', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, des=Column{name='des', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, recent=Column{name='recent', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
预期与发现之间的差异是
Expected: notNull=true
Found: notNull=false
所以我尝试修改创建表代码
database.execSQL("CREATE TABLE `USER` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `word` TEXT NOT NULL, `des` TEXT NOT NULL, `ref` TEXT NOT NULL, `recent` INTEGER NOT NULL, `bookmark` INTEGER NOT NULL, `addByUser` INTEGER NOT NULL, `uploaded` INTEGER NOT NULL)")
但是这次我得到这个错误:
android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed: USER.ref (Sqlite code 1299), (OS error - 2:No such file or directory)
at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:742)
我也尝试更改表和列,但得到相同的错误。
我该如何解决?
答案 0 :(得分:0)
您可以复制查询以创建表或从生成的会议室数据库文件中修改表。
只需双击并查找_Impl。
您的问题与表中的NON NULL
数据类型有关,您需要将这些字段指定为NON NULL
并处理在房间迁移期间需要分配的DEFAULT
值。
答案 1 :(得分:0)
您不需要建立新表 创建类似的方法:
private static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE `WordTable` ADD COLUMN ref STRING");
}
};
并调用数据库创建方法,例如:
Room.databaseBuilder(/*parameter want */).addMigrations(MIGRATION_1_2).allowMainThreadQueries().build();
答案 2 :(得分:0)
您可以使用ALTER TABLE
查询并仅提供迁移
private static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE `table_name` ADD COLUMN `column_name` {type} DEFAULT {defaultValue} NOT NULL");
}
};
当您尝试更改表时,应为表中已经存在的所有其他记录提供默认值。
答案 3 :(得分:0)
错误消息中的Expected和Found之间的区别是表中的非null约束。
如果希望这些行可为空,则将它们的变量定义为没有默认值的对象,并构造一个定义所需行的构造函数。实例化变量时不要同时实例化行值!
如果您希望行从不接受Null,请在SQLite查询的行末尾添加NOT NULL,而不必更改模型类。