如何将sqlite中的现有表迁移到Android中的房间数据库

时间:2019-09-18 13:32:32

标签: android database sqlite migration android-room

我正在尝试将sqlite中的现有数据迁移到会议室数据库中。

我提供了迁移规则。

This is the migration rule:
private  static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
           database.execSQL("CREATE TABLE  temp_account (\n"+
                    " _id  INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,"
                    + "name TEXT NOT NULL UNIQUE, "
                    +  "number TEXT DEFAULT 0, "
                    +  "balance REAL DEFAULT 0 NOT NULL, "
                    +  "account_type TEXT);");

            database.execSQL("INSERT INTO temp_account( name,number,balance,account_type) " +
                    "SELECT  name,number,balance,account_type FROM account");

            database.execSQL("DROP TABLE account");

            database.execSQL("ALTER TABLE temp_account RENAME TO account;");
;
Below is my original table which I want to migrate:
"CREATE TABLE  account (\n"+
                    " _id  INTEGER PRIMARY KEY AUTOINCREMENT ,"
                    + "name TEXT NOT NULL UNIQUE, "
                    +  "number TEXT DEFAULT 0, "
                    +  "balance REAL , "
                    +  "account_type TEXT);");

虽然它可以在大多数设备上运行,但该应用在少数设备上崩溃。崩溃并非特定于任何设备或android版本。以下是Google的错误报告:

java.lang.RuntimeException: 
  at android.os.AsyncTask$3.done (AsyncTask.java:354)
  at java.util.concurrent.FutureTask.finishCompletion (FutureTask.java:383)
  at java.util.concurrent.FutureTask.setException (FutureTask.java:252)
  at java.util.concurrent.FutureTask.run (FutureTask.java:271)
  at android.os.AsyncTask$SerialExecutor$1.run (AsyncTask.java:245)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
  at java.lang.Thread.run (Thread.java:764)
Caused by: android.database.sqlite.SQLiteConstraintException:   at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
    at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:796)
    at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)

我们非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我认为问题在于原始表中的某些余额 NULL ,并且在插入新添加的 NOT NULL 时约束冲突。

您可以通过用任一

替换 balance 来解决此问题
  • CASE WHEN balance IS NULL THEN 0 ELSE balance END
  • coalesce(balance,0)

两者都将有效地使用0而不是NULL的值。

例如

database.execSQL("INSERT INTO temp_account( name,number,balance,account_type) " +
                "SELECT  name,number,
                    coalesce(balance,0),
                    account_type FROM account");

database.execSQL("INSERT INTO temp_account( name,number,balance,account_type) " +
                "SELECT  name,number,
                    CASE WHEN balance IS NULL THEN 0 ELSE balance END,
                    account_type FROM account");