简体   繁体   中英

How to delete column in next version of room database Android?

How to delete a column in next version of room database android.DROp or delete not working.?

@Database(entities = {User.class, AdTime.class}, version = 1, exportSchema = false)
  public abstract class AppDataBase extends RoomDatabase {

  private static AppDataBase INSTANCE;

  public abstract UserDao userModel();

  public abstract AdDao adModel();

  public static AppDataBase getInMemoryDatabase(Context context) {

    if (INSTANCE == null) {
        INSTANCE = Room.databaseBuilder(context, AppDataBase.class, "adrider")
                // To simplify the codelab, allow queries on the main thread.
                // Don't do this on a real app! See PersistenceBasicSample for an example.
                .allowMainThreadQueries()
              //  .addMigrations(MIGRATION_1_2)
                //  .fallbackToDestructiveMigration()
                .build();
      }
      return INSTANCE;
    }

  static final Migration MIGRATION_1_2=new Migration(1,2) {
      @Override
      public void migrate(@NonNull SupportSQLiteDatabase database) {
          database.execSQL("ALTER TABLE User "
                + "DROP Download");
      }
  };

}

You have to do 4 steps:
1. Create the new table
2. Copy the data
3. Remove the old table
4. Change the table name to the correct one

static final Migration MIGRATION_1_2 = new Migration(1, 2) {

    @Override
    public void migrate(SupportSQLiteDatabase database) {
        // Create the new table
        database.execSQL(
                "CREATE TABLE users_new (userid TEXT, username TEXT, last_update INTEGER, 
        PRIMARY KEY(userid))");
        // Copy the data
        database.execSQL(
                "INSERT INTO users_new (userid, username, last_update) SELECT userid, 
        username, last_update FROM users");
        // Remove the old table
        database.execSQL("DROP TABLE users");
        // Change the table name to the correct one
        database.execSQL("ALTER TABLE users_new RENAME TO users");
    }

};

The principle should still be the same, as you are using SQLite underneath Room. So you should be able to issue the same SQL statements described in that link. Have you tried?

database.execSQL("CREATE TABLE t1_backup AS SELECT a, b FROM t1");
database.execSQL("DROP TABLE t1");
database.execSQL("ALTER TABLE t1_backup RENAME TO t1");

Obviously change the table names and column names to suit your scenario.

You can use a helper for doing table alterations like: Add, Delete, Rename or Change Scheme of a column.

It handles the creation of a temp table, filling it with data, and deleting the old table.

Helper source code: https://gist.github.com/Benjiko99/23fbeee37d1d9f9a8b52ad21fc2585b9

fun alterTableUsage(database: SupportSQLiteDatabase) {
    DbMigrationsHelper.alterTable(
        db = database,
        tableName = "Reservations",
        columns = mapOf(
            "id INTEGER".toExisting(), // Retains without changes
            "title TEXT".toExisting("name"), // Renames column "name" to "title"
            "description TEXT".toNothing(), // Adds a new column
            "creatorId INTEGER NOT NULL".toExisting() // Change scheme from "creatorId INTEGER" and add "NON NULL"
            // Any columns that existed in the "Reservations" table
            // and aren't specified in this map will be removed
        ),
        primaryKeys = listOf("id") // Add more than one key to create a compound primary key
    )
}

My answer is very similar to what @Pedro Romao has given except that I have removed the extra unnecessary "NOT NULL" included in the sql statements. It should be added only where necessary as it might even cause an error where a column is allowed to be Null.

    // Create a table that would be your new table. Specify the type of each field and include NON NULL when field can't be null for example in the case of a primary key
    database.execSQL("CREATE TABLE Users_backup (id INTEGER NOT NULL, name TEXT, PRIMARY KEY(id))"); 
    // Copy the desired columns from the old table into this new table
    database.execSQL("INSERT INTO Users_backup (id, name) SELECT id, name FROM Users");
    // Delete the old table
    database.execSQL("DROP TABLE Users");
    // Rename the new table to the old table's name so that the rest of your code can recognize this table as the former one.
    database.execSQL("ALTER TABLE Users_backup RENAME TO Users");

Thanks to @MrVasilev and @nobody special. In my case I got an error during migration.

I had to create the table with the exactly original structure by setting the column types, force NOT NULL and set the PRIMARY KEY.

database.execSQL("CREATE TABLE backup_table (id INTEGER PRIMARY KEY NOT NULL, title TEXT NOT NULL, account TEXT NOT NULL, hash TEXT NOT NULL, sequence INTEGER NOT NULL)")
database.execSQL("INSERT INTO table_backup(id, title, account, hash, sequence) SELECT id, title, account, hash, sequence FROM original_table")
database.execSQL("DROP TABLE original_table")
database.execSQL("ALTER TABLE backup_table RENAME TO original_table")

Read the logs to understand whats wrong during migration:

Migration didn't properly handle 

Expected: TableInfo{name='my_table', columns={sequence=Column{name='sequence', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1}, title=Column{name='title', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, account=Column{name='account', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, hash=Column{name='hash', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]} 

Found: TableInfo{name='my_table', columns={sequence=Column{name='sequence', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1}, title=Column{name='title', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, account=Column{name='account', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, hash=Column{name='hash', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM