[英]android room database returns wrong schema table
我有一個數據庫遷移問題
使用:Kotlin,房間
我想將數據庫從 1 升級到 3
我已經成功地從 1 到 2 以及從 2 到 3 完美的遷移。
但是,當我嘗試從 1 升級到 3 時,在查詢的 3 遷移結果中返回版本 1 的架構。
版本 1:
賬戶表
列:地址、類型、id、備忘錄
版本 2:
賬戶表
欄目:地址、類型、路徑、備忘錄
版本 3:
賬戶表
欄目:地址、類型、路徑、備忘錄、順序
private val MIGRATION_1_2: Migration = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.beginTransaction()
try {
database.execSQL("""
CREATE TABLE Account_tmp (
address TEXT NOT NULL, type TEXT, path TEXT, memo TEXT,
PRIMARY KEY(address))""")
database.query("SELECT * FROM Account").use { cursor ->
if (cursor != null && cursor.count > 0) {
while (cursor.moveToNext()) {
val address = cursor.getString(cursor.getColumnIndex("address"))
val type = cursor.getString(cursor.getColumnIndex("type"))
val path = "Id:" + cursor.getInt(cursor.getColumnIndex("id"))
val memo = cursor.getInt(cursor.getColumnIndex("memo"))
val values = ContentValues()
values.put("address", address)
values.put("type", type)
values.put("path", path)
values.put("memo", memo)
database.insert("Account_tmp", SQLiteDatabase.CONFLICT_FAIL, values)
}
}
}
database.execSQL("DROP TABLE IF EXISTS Account")
database.execSQL("ALTER TABLE Account_tmp RENAME TO Account")
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
}
private val MIGRATION_2_3: Migration = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.beginTransaction()
try {
database.execSQL("""
CREATE TABLE Account_tmp (
address TEXT NOT NULL, type TEXT, path TEXT, memo TEXT, order TEXT,
PRIMARY KEY(address))""")
database.query("SELECT * FROM Account").use { cursor ->
if (cursor != null && cursor.count > 0) {
while (cursor.moveToNext()) {
val address = cursor.getString(cursor.getColumnIndex("address"))
val type = cursor.getString(cursor.getColumnIndex("type"))
val path = cursor.getString(cursor.getColumnIndex("path")) ************************ // getting error -> because table hasn't path column
val memo = cursor.getInt(cursor.getColumnIndex("memo"))
val values = ContentValues()
values.put("address", address)
values.put("type", type)
values.put("path", path)
values.put("memo", memo)
database.insert("Account_tmp", SQLiteDatabase.CONFLICT_FAIL, values)
}
}
}
database.execSQL("DROP TABLE IF EXISTS Account")
database.execSQL("ALTER TABLE Account_tmp RENAME TO Account")
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
}
當我嘗試將 db 從 1 升級到 3 時,MIGRATION_2_3 中發生異常
而且在調試的時候,查詢結果很尷尬....
private val MIGRATION_1_2: Migration = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.beginTransaction()
try {
database.execSQL("""
CREATE TABLE Account_tmp (
address TEXT NOT NULL, type TEXT, path TEXT, memo TEXT,
PRIMARY KEY(address))""")
database.query("SELECT * FROM Account").use { cursor ->
if (cursor != null && cursor.count > 0) {
while (cursor.moveToNext()) {
val address = cursor.getString(cursor.getColumnIndex("address"))
val type = cursor.getString(cursor.getColumnIndex("type"))
val path = "Id:" + cursor.getInt(cursor.getColumnIndex("id"))
val memo = cursor.getInt(cursor.getColumnIndex("memo"))
val values = ContentValues()
values.put("address", address)
values.put("type", type)
values.put("path", path)
values.put("memo", memo)
database.insert("Account_tmp", SQLiteDatabase.CONFLICT_FAIL, values)
}
}
}
database.execSQL("DROP TABLE IF EXISTS Account")
database.execSQL("ALTER TABLE Account_tmp RENAME TO Account")
database.setTransactionSuccessful()
} finally {
database.endTransaction()
// database.query("SELECT * FROM Account") have {address, type, id, memo} (ver 1 schema) ****** -> why??
}
}
private val MIGRATION_2_3: Migration = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.beginTransaction()
try {
database.execSQL("""
CREATE TABLE Account_tmp (
address TEXT NOT NULL, type TEXT, path TEXT, memo TEXT, order TEXT,
PRIMARY KEY(address))""")
database.query("SELECT * FROM Account").use { cursor ->
if (cursor != null && cursor.count > 0) {
while (cursor.moveToNext()) {
// cursor's column has {address, type, id, memo} (ver 1 schema), not (address, type, path, memo)(ver 2 schema) -> why??
val address = cursor.getString(cursor.getColumnIndex("address"))
val type = cursor.getString(cursor.getColumnIndex("type"))
val path = cursor.getString(cursor.getColumnIndex("path")) // exception because account table has not path.. still has id column
val memo = cursor.getInt(cursor.getColumnIndex("memo"))
val values = ContentValues()
values.put("address", address)
values.put("type", type)
values.put("path", path)
values.put("memo", memo)
database.insert("Account_tmp", SQLiteDatabase.CONFLICT_FAIL, values)
}
}
}
database.execSQL("DROP TABLE IF EXISTS Account")
database.execSQL("ALTER TABLE Account_tmp RENAME TO Account")
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
}
我不知道為什么 database.query("SELECT * FROM Account") 返回錯誤的數據庫架構........
甚至,如果我在 rename 下面添加無意義的查詢來查詢,那么我可以成功地從 1 到 3 版本遷移
private val MIGRATION_1_2: Migration = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.beginTransaction()
try {
database.execSQL("""
CREATE TABLE Account_tmp (
address TEXT NOT NULL, type TEXT, path TEXT, memo TEXT,
PRIMARY KEY(address))""")
database.query("SELECT * FROM Account").use { cursor ->
if (cursor != null && cursor.count > 0) {
while (cursor.moveToNext()) {
val address = cursor.getString(cursor.getColumnIndex("address"))
val type = cursor.getString(cursor.getColumnIndex("type"))
val path = "Id:" + cursor.getInt(cursor.getColumnIndex("id"))
val memo = cursor.getInt(cursor.getColumnIndex("memo"))
val values = ContentValues()
values.put("address", address)
values.put("type", type)
values.put("path", path)
values.put("memo", memo)
database.insert("Account_tmp", SQLiteDatabase.CONFLICT_FAIL, values)
}
}
}
database.execSQL("DROP TABLE IF EXISTS Account")
database.execSQL("ALTER TABLE Account_tmp RENAME TO Account")
database.query("SELECT * FROM Account").use { cursor ->
Log.e(TAG, "MIGRATION_1_2, account size=${cursor.count}")
// If I add this code, Migration from 1 to 3 success!!!!
}
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
}
為什么??????????????????
我想知道為什么!!!!
請幫我
這是我的數據庫代碼
companion object {
private const val TAG = "TestDatabase"
@Volatile
private var instance: TestDatabase? = null
fun getInstance(context: Context): TestDatabase =
instance ?: synchronized(this) {
instance
?: buildDatabase(context).also { instance = it }
}
private fun buildDatabase(context: Context) =
Room.databaseBuilder(context, TestDatabase::class.java, "test_database.db")
.allowMainThreadQueries()
.addMigrations(MIGRATION_1_2)
.addMigrations(MIGRATION_2_3)
.build()
private val MIGRATION_1_2: Migration = object : Migration(1, 2) {
...
}
private val MIGRATION_2_3: Migration = object : Migration(2, 3) {
...
}
}
我相信您的問題是您正在使用關鍵字,即在MIGRATION_2_3中添加的列名的順序。
日志將包含類似於以下內容的內容:-
2019-12-10 20:55:51.508 27554-27554/a.so59253634migrationschemanotchanging E/AndroidRuntime: FATAL EXCEPTION: main
Process: a.so59253634migrationschemanotchanging, PID: 27554
java.lang.RuntimeException: Unable to start activity ComponentInfo{a.so59253634migrationschemanotchanging/a.so59253634migrationschemanotchanging.MainActivity}: android.database.sqlite.SQLiteException: near "order": syntax error (code 1 SQLITE_ERROR): , while compiling: CREATE TABLE Account_tmp (
address TEXT NOT NULL, type TEXT, path TEXT, memo TEXT, order TEXT,
PRIMARY KEY(address))
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: android.database.sqlite.SQLiteException: near "order": syntax error (code 1 SQLITE_ERROR): , while compiling: CREATE TABLE Account_tmp (
address TEXT NOT NULL, type TEXT, path TEXT, memo TEXT, order TEXT,
PRIMARY KEY(address))
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:986)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:593)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:590)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:61)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:33)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1805)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1733)
at androidx.sqlite.db.framework.FrameworkSQLiteDatabase.execSQL(FrameworkSQLiteDatabase.java:242)
at a.so59253634migrationschemanotchanging.TestDatabase$Companion$MIGRATION_2_3$1.migrate(AppDatabase.kt:80)
你可以用
`order`
或者不使用 order 關鍵字作為列的名稱。
例如:-
private val MIGRATION_2_3: Migration = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.beginTransaction()
try {
database.execSQL(
"""
CREATE TABLE Account_tmp (
address TEXT NOT NULL, type TEXT, path TEXT, memo TEXT, `order` TEXT,
PRIMARY KEY(address))"""
)
database.query("SELECT * FROM Account").use { cursor ->
if (cursor != null && cursor.count > 0) {
while (cursor.moveToNext()) {
// cursor's column has {address, type, id, memo} (ver 1 schema), not (address, type, path, memo)(ver 2 schema) -> why??
val address = cursor.getString(cursor.getColumnIndex("address"))
val type = cursor.getString(cursor.getColumnIndex("type"))
val path =
cursor.getString(cursor.getColumnIndex("path")) // exception because account table has not path.. still has id column
val memo = cursor.getInt(cursor.getColumnIndex("memo"))
val values = ContentValues()
values.put("address", address)
values.put("type", type)
values.put("path", path)
values.put("memo", memo)
database.insert(
"Account_tmp",
SQLiteDatabase.CONFLICT_FAIL,
values
)
}
}
}
database.execSQL("DROP TABLE IF EXISTS Account")
database.execSQL("ALTER TABLE Account_tmp RENAME TO Account")
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.