SQFLite adalah penyimpanan lokal berupa table yang sering digunakan pada project Flutter. Setiap pengembangan aplikasi, tak jarang kita memukan kondisi, di mana kita harus menambahkan table baru pada atau mengubah column pada table yang sebelumnya telah digunakan. Pada kondisi tersebut dibutuhkan lah migration.
Tulisan ini termasuk ke pada rangkaian pembahasan penyimpanan data lokal pada Flutter:
- Penyimpanan data lokal pada Flutter (shared_preferences)
- Penyimpanan data lokal pada Flutter (sqflite)
- [Tulisan ini] Update schema pada SQFLite
Why?
Migration harus dilakukan, karena jika tidak dilakukan akan terjadi error ketika device yang telah pernah menginstall aplikasi, melakukan pembaruan. Sedangkan untuk device yang baru pertama kali menginstall aplikasi, error mungkin tidak akan terjadi.
Schema
Pada tulisan sebelumnya kita telah memiliki satu table, yaitu table mahasiswa. Kali ini kita akan menambahkan column baru pada table tersebut, dan juga membuat table baru. Berikut schemanya:

Yuk Ngoding
Sesuai dengan schema sebelumnya, kita akan menambahkan column baru di table Student dan juga membuat satu table baru. Langkah pertama, kita tambahkan propery baru di class Student, seperti berikut:
import '../commons/const.dart';
class StudentModel {
String id;
String name;
String department;
int sks;
String? address;
StudentModel({
required this.id,
required this.name,
required this.department,
required this.sks,
this.address,
});
// Convert into a Map. The keys must correspond to the names of the
// columns in the database.
Map<String, dynamic> toMap() {
return {
Constant.studentId: id,
Constant.studentName: name,
Constant.studentDepartment: department,
Constant.studentSKS: sks,
Constant.studentAddress: address,
};
}
// Implement toString to make it easier to see information about
// each student when using the print statement.
@override
String toString() {
return 'Student{${Constant.studentId}: $id, ${Constant.studentName}: $name, '
'${Constant.studentDepartment}: $department, '
'${Constant.studentSKS}: $sks, ${Constant.studentAddress}: $address}';
}
}
Setelah itu kita buat class Organization untuk table baru nantinya.
import '../commons/const.dart';
class OrganizationModel {
String id;
String name;
OrganizationModel({
required this.id,
required this.name,
});
// Convert into a Map. The keys must correspond to the names of the
// columns in the database.
Map<String, dynamic> toMap() {
return {
Constant.organizationId: id,
Constant.organizationName: name,
};
}
// Implement toString to make it easier to see information about
// each student when using the print statement.
@override
String toString() {
return 'Organization{${Constant.studentId}: $id, '
'${Constant.studentName}: $name}';
}
}
Setelah memperbarui model, kita lanjut perbarui class Constant untuk nama column-column baru.
class Constant {
static const studentId = 'id';
static const studentName = 'name';
static const studentDepartment = 'department';
static const studentSKS = 'sks';
static const studentAddress = 'address';
static const organizationId = 'id';
static const organizationName = 'name';
}
Pada code pada MySQFLite.dart di tulisan sebelumnya menjadi seperti berikut:
class MySqflite {
...
static final _databaseV1 = 1;
static final _databaseV2 = 2;
static const tableStudent = 'Student';
static const tableOrganization = 'Organization'; // new Table
...
_initDatabase() async {
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, _databaseName);
return await openDatabase(path, version: _databaseV2,
onCreate: (db, version) async {
var batch = db.batch();
_onCreateTableStudentV2(batch);
_onCreateTableOrganizationV2(batch);
await batch.commit();
}, onUpgrade: (db, oldVersion, newVersion) async {
var batch = db.batch();
if (oldVersion == _databaseV1) {
_onUpdateTableStudentV1ToV2(batch);
_onCreateTableOrganizationV2(batch);
}
await batch.commit();
});
}
void _onCreateTableStudentV2(Batch batch) async {
batch.execute('''
CREATE TABLE $tableStudent (
${Constant.studentId} TEXT PRIMARY KEY,
${Constant.studentName} TEXT,
${Constant.studentDepartment} TEXT,
${Constant.studentSKS} INTEGER,
${Constant.studentAddress} TEXT
)
''');
}
void _onUpdateTableStudentV1ToV2(Batch batch) async {
batch.execute(
'''ALTER TABLE $tableStudent ADD COLUMN ${Constant.studentAddress} TEXT''');
}
void _onCreateTableOrganizationV2(Batch batch) async {
batch.execute('''
CREATE TABLE $tableOrganization (
${Constant.organizationName} TEXT,
${Constant.organizationId} TEXT
)
''');
}
...
}
- Pada function _initDatabase() kita menaikkan versi database menjadi _databaseV2.
- Pada bagian onCreate database, kita menjalankan function untuk membuat 2 table sesuai dengan schema baru yang kita miliki
- Sedangkan untuk onUpgrade kita melakukan pengecekan versi, melakukan alter untuk perubahan schema pada table mahasiswa, dan membuat table baru untuk table organisasi.
- Setelah melakukan onUpgrade (migration), kita bisa mengoperasikan database, seperti menambah data, mengambil data, tanpa menemukan error terkait version atau schema yang kita gunakan.
Hasil
Untuk melihat keseluruhan codenya (termasuk 2 part sebelumnya), temen” bisa mengunjungi github ya.
Berikut merupakan hasil dari memasukkan data sebelum migration dilakukan, dan memasukkan data setelah migration dilakukan.

Untuk data sebelum migration, address akan bernilai null. Oleh karena itu disini kita tampilkan tulisan Empty.
Sekian tulisan kali ini, terimakasih dan semoga bermanfaat ya 😀. Tulisan ini termasuk ke pada rangkaian pembahasan penyimpanan data lokal pada Flutter:
- Penyimpanan data lokal pada Flutter (shared_preferences)
- Penyimpanan data lokal pada Flutter (sqflite)
- [Tulisan ini] Update schema pada SQFLite
Oh iya di website ini ada tulisan menarik lainnya juga loh, seperti berikut: