I'm referring to https://developer.android.com/training/data-storage/room/migrating-db-versions.md#handle-default-values-migrations
I'm kinna confused with the guideline. My understanding is that
If you add a NON NULL
new column
@Entity
public class Song {
// ...
@NonNull
final String tag;
}
Using the following ALTER TABLE
migration strategy is wrong
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL(
"ALTER TABLE Song ADD COLUMN tag TEXT NOT NULL DEFAULT ''");
}
};
You need to use the following drop and re-create
migration strategy
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE new_Song (" +
"id INTEGER PRIMARY KEY NOT NULL," +
"name TEXT," +
"tag TEXT NOT NULL DEFAULT '')");
database.execSQL("INSERT INTO new_Song (id, name, tag) " +
"SELECT id, name, tag FROM Song");
database.execSQL("DROP TABLE Song");
database.execSQL("ALTER TABLE new_Song RENAME TO Song");
}
};
That even confuse me. Isn't both methods, will end up having the same column - tag TEXT NOT NULL DEFAULT ''
? How does the former method is marked as a problematic method?
Can someone can provide an simple example, to explain what problem might occur by using ALTER TABLE
, and how drop and re-create
might overcome the problem?
Thanks.
In Object Explorer, right-click the table with columns for which you want to change the scale and select Design. Select the column for which you want to specify a default value. In the Column Properties tab, enter the new default value in the Default Value or Binding property.
Changing a Column's Default Value. To set a new default for a column, use a command like: ALTER TABLE products ALTER COLUMN price SET DEFAULT 7.77; Note that this doesn't affect any existing rows in the table, it just changes the default for future INSERT commands.
After having discussion with the original author via https://issuetracker.google.com/issues/137515134, here's a simple to understood example.
@Entity
public class Song {
@PrimaryKey
final long id;
}
@Entity
public class Song {
@PrimaryKey
final long id;
@NonNull
final String tag;
}
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL(
"ALTER TABLE Song ADD COLUMN tag TEXT NOT NULL DEFAULT ''");
}
};
@Entity
public class Song {
@PrimaryKey
final long id;
@ColumnInfo(defaultValue = "")
@NonNull
final String tag;
}
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE new_Song (" +
"id INTEGER PRIMARY KEY NOT NULL," +
"tag TEXT NOT NULL DEFAULT '')");
database.execSQL("INSERT INTO new_Song (id, tag) " +
"SELECT id, tag FROM Song");
database.execSQL("DROP TABLE Song");
database.execSQL("ALTER TABLE new_Song RENAME TO Song");
}
};
Database version 2 (who never went through MIGRATION_1_2) doesn't have DEFAULT '' in its SQLite schema. MIGRATION_2_3 is required.
Database version 2 (who already went through MIGRATION_1_2) has DEFAULT '' in its SQLite schema. MIGRATION_2_3 has no harm.
In SQLite, there is no way to ALTER an column to add DEFAULT '' constraint.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With