Flutter › SQLite & Local Databases (sqflite)

How do you properly implement database migrations in sqflite, correctly handling a schema change such as adding a genuinely new column when a user actually updates to a newer version of your app?

Intermediate

Answer

sqflite's openDatabase method accepts an onUpgrade callback, which properly receives both the previous existing database version number and the genuinely new target version number, letting you write conditional migration logic that properly runs the exact correct specific SQL statements genuinely needed to transform an existing database from any given older version up to your genuinely current latest schema, such as running an ALTER TABLE statement to properly add a genuinely new required column, and properly incrementing your database's own version number every single time you actually make a genuine schema change ensures this migration logic correctly and reliably runs for every single existing user updating from any of your app's own several previous released versions.
onUpgrade: (db, oldVersion, newVersion) async {
  if (oldVersion < 2) {
    await db.execute('ALTER TABLE orders ADD COLUMN notes TEXT');
  }
}
Real-world example A note taking app properly adds a genuinely new notes column to their existing orders table through a correctly implemented onUpgrade migration, ensuring every single existing user's own previously already saved order data remains fully intact and correctly accessible after they actually update to the app's genuinely latest version.

Common follow-ups: What genuinely happens if a user skips several versions at once, upgrading directly from a genuinely very old version straight to your latest current one?;How do you actually properly and thoroughly test a database migration before actually genuinely releasing it to real production users?