SqfLite No such table (code 1 SQLITE_ERROR) - database

Maybe this question was already answered but I try to add sqfLite to my project but I get this error:
In my debug console:
no such table: infotable in "SELECT * FROM infotable"
This is my code:
final String infoTable = 'infotable';
final String columnID = '_id';
final String columnName = 'name';
final String columnCivilStatus = 'civil';
final String columnWorking = 'working';
final String columnJobTitle = 'job';
final String columnWorkingDomain = 'workingdomain';
final String columnMonthlyIncome = 'monthlyincome';
class SqfLite {
int id;
int sliderValue;
int monthChoiceChip;
String reasonChoiceChip;
String name;
String civilStatus;
int working;
String jobTitle;
int workingDomain;
String monthlyIncome;
String currency;
Position latitude;
Position longitude;
Map<String, dynamic> toMap() {
var map = <String, dynamic>{
columnCivilStatus: civilStatus,
columnJobTitle: jobTitle,
columnMonthlyIncome: monthlyIncome,
columnWorkingDomain: workingDomain,
columnWorking: working,
columnName: name,
};
if (id != null) {
map[columnID] = id;
}
return map;
}
SqfLite();
SqfLite.fromMap(Map<String, dynamic> map) {
id = map[columnID];
name = map[columnName];
civilStatus = map[columnCivilStatus];
working = map[columnWorking];
jobTitle = map[columnJobTitle];
workingDomain = map[columnWorkingDomain];
monthlyIncome = map[columnMonthlyIncome];
}
}
class SqfLiteProvider {
Database db;
Future open(String path) async {
db = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute('''
create table $infoTable (
$columnID integer primary key autoincrement,
$columnName text not null,
$columnCivilStatus text not null,
$columnWorking integer not null,
$columnJobTitle text not null,
$columnWorkingDomain integer not null,
$columnMonthlyIncome text not null)
''');
});
}
Future<SqfLite> getSqfLite(int id) async {
List<Map> maps = await db.query(infoTable,
columns: [
columnID,
columnName,
columnCivilStatus,
columnWorking,
columnJobTitle,
columnWorkingDomain,
columnMonthlyIncome,
],
where: '$columnID = ?',
whereArgs: [id]);
if (maps.length > 0) {
return SqfLite.fromMap(maps.first);
}
return null;
}
Future close() async => db.close();
}
I get the error here:
Future<void> openDataBase() async {
db = await openDatabase('infotable.db');
records = await db.query('infotable');
mapRead = records.first;
....
}
I've followed the example from the official page of the plugin
I can't use the latest version because of some pubspec.yaml conflicts.
I've tried to flutter clean and reinstalling the app but it didn't work

You have defined the open method inside SqfLiteProvider, but you are not using it. Instead, you are calling the same openDatabase('infotable.db'); method from sqflite package where the onCreate callback is not defined - you get an error.
So, instead of calling db = await openDatabase('infotable.db'); directly, use the SqfLiteProvider.open() you have defined.

Related

How to fix "The non-nullable variable '_db' must be initialized. Try adding an initializer expression"

"The non-nullable variable '_db' must be initialized. Try adding an initializer expression"
Could anyone help me with this non-nullable error?
I am using flutter to make an android app and while using the 'sqflite' and making a database, this error pops up I don't know how to really fix this
Here is my Code below,
I am using the last version of Flutter & Dart,
import 'dart:io';
import 'package:newtodoapp/taskmodel.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
class DatabaseHelper {
static final DatabaseHelper instance = DatabaseHelper._instance();
static Database _db;
DatabaseHelper._instance();
String tasksTable = 'task_table';
String colId = 'id';
String colTitle = 'title';
String colDate = 'date';
String colPriority = 'priority';
String colStatus = 'status';
// Task Tables
// Id | Title | Date | Priority | Status
// 0 '' '' '' 0
// 2 '' '' '' 0
// 3 '' '' '' 0
Future<Database> get db async {
if (_db == null) {
_db = await _initDb();
}
return _db;
}
Future<Database> _initDb() async {
Directory dir = await getApplicationDocumentsDirectory();
String path = dir.path + '/todo_list.db';
final todoListDb =
await openDatabase(path, version: 1, onCreate: _createDb);
return todoListDb;
}
void _createDb(Database db, int version) async {
await db.execute(
'CREATE TABLE $tasksTable($colId INTEGER PRIMARY KEY AUTOINCREMENT,'
' $colTitle TEXT, $colDate TEXT, $colPriority TEXT, $colStatus INTEGER)',
);
}
Future<List<Map<String, dynamic>>> getTaskMapList() async {
Database db = await this.db;
final List<Map<String, dynamic>> result = await db.query(tasksTable);
return result;
}
Future<List<Task>> getTaskList() async {
final List<Map<String, dynamic>> taskMapList = await getTaskMapList();
final List<Task> taskList = [];
taskMapList.forEach((taskMap) {
taskList.add(Task.fromMap(taskMap));
});
taskList.sort((taskA, taskB) => taskA.date.compareTo(taskB.date));
return taskList;
}
Future<int> insertTask(Task task) async {
Database db = await this.db;
final int result = await db.insert(tasksTable, task.toMap());
return result;
}
Future<int> updateTask(Task task) async {
Database db = await this.db;
final int result = await db.update(
tasksTable,
task.toMap(),
where: '$colId = ?',
whereArgs: [task.id],
);
return result;
}
Future<int> deleteTask(int id) async {
Database db = await this.db;
final int result = await db.delete(
tasksTable,
where: '$colId = ?',
whereArgs: [id],
);
return result;
}
}
declare your variable like this.
static Database? _db;

Caused By : SQL(query) error or missing database. - In Flutter/Dart

I was trying to build an app that takes in the Title, Date, Link, Priority level and then displays them using Flutter and SQLite.
I originally built it without 'link' and it was working perfectly, but when I added the filed 'link' it gives me this error:
E/flutter ( 8491): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: DatabaseException(table task_table has no column named link (code 1): , while compiling: INSERT INTO task_table (title, date, link, priority, status) VALUES (?, ?, ?, ?, ?)
E/flutter ( 8491): #################################################################
E/flutter ( 8491): Error Code : 1 (SQLITE_ERROR)
E/flutter ( 8491): Caused By : SQL(query) error or missing database.
E/flutter ( 8491): (table task_table has no column named link (code 1): , while compiling: INSERT INTO task_table (title, date, link, priority, status) VALUES (?, ?, ?, ?, ?))
E/flutter ( 8491): #################################################################) sql 'INSERT INTO task_table (title, date, link, priority, status) VALUES (?, ?, ?, ?, ?)' args [math, 2021-04-28T00:00:00.000, google, Medium, 0]}
The code associated with this is distributed in two files: a database helper file that basically stores all the functions for database management
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:todo/models/task_model.dart';
class DatabaseHelper {
static final DatabaseHelper instance = DatabaseHelper._instance();
static Database _db;
DatabaseHelper._instance();
String taskTable = 'task_table';
String colId = 'id';
String colTitle = 'title';
String colDate = 'date';
String colLink = 'link';
String colPriority = 'priority';
String colStatus = 'status';
// task tables
// Id | Title | Date | Link | Priority | Status
// 0 '' '' '' ''
// 2 '' '' '' ''
// 3 '' '' '' ''
Future<Database> get db async {
if (_db == null) {
_db = await _initDb();
}
return _db;
}
Future<Database> _initDb() async {
Directory dir = await getApplicationDocumentsDirectory();
String path = dir.path + 'todo_list.db';
final todoListDb =
await openDatabase(path, version: 1, onCreate: _createDb);
return todoListDb;
}
void _createDb(Database db, int version) async {
await db.execute(
'CREATE TABLE $taskTable($colId INTEGER PRIMARY KEY AUTOINCREMENT, $colTitle TEXT, $colDate TEXT, $colLink TEXT, $colPriority TEXT, $colStatus INTEGER)');
}
Future<List<Map<String, dynamic>>> getTaskMapList() async {
Database db = await this.db;
final List<Map<String, dynamic>> result = await db.query(taskTable);
return result;
}
Future<List<Task>> getTaskList() async {
final List<Map<String, dynamic>> taskMapList = await getTaskMapList();
final List<Task> taskList = [];
taskMapList.forEach((taskMap) {
taskList.add(Task.fromMap(taskMap));
});
taskList.sort((taskA, taskB) => taskA.date.compareTo(taskB.date));
return taskList;
}
Future<int> insertTask(Task task) async {
Database db = await this.db;
final int result = await db.insert(taskTable, task.toMap());
return result;
}
Future<int> updateTask(Task task) async {
Database db = await this.db;
final int result = await db.update(taskTable, task.toMap(),
where: '$colId = ?', whereArgs: [task.id]);
return result;
}
Future<int> deleteTask(int id) async {
Database db = await this.db;
final int result =
await db.delete(taskTable, where: '$colId = ?', whereArgs: [id]);
return result;
}
}
And the second file is a database model file, which contains the database creation etc. :
class Task {
int id;
String title;
DateTime date;
String link;
String priority;
int status; // 0 - complete, 1- complete
Task({
this.title,
this.date,
this.link,
this.priority,
this.status,
});
Task.withId({
this.id,
this.title,
this.date,
this.link,
this.priority,
this.status,
});
Map<String, dynamic> toMap() {
final map = Map<String, dynamic>();
if (id != null) {
map['id'] = id;
}
map['title'] = title;
map['date'] = date.toIso8601String();
map['link'] = link;
map['priority'] = priority;
map['status'] = status;
return map;
}
factory Task.fromMap(Map<String, dynamic> map) {
return Task.withId(
id: map['id'],
title: map['title'],
date: DateTime.parse(map['date']),
link: map['link'],
priority: map['priority'],
status: map['status']);
}
}
This is my first time working with databases in flutter so any feedback would be greatly appreciated. Thank you
The error says that you don't have the column available in the table. The problem is that the db is not created every time you start the app. There are two solutions to your problem here:
For debug purposes, just delete the app and re-run the code, this will regenerate the database with the correct columns. WARNING: this is just for debug only, not for production.
For production, when you add changes on database, you have to increase the database version, in your case from 1 to let's say 2. Next, the openDatabase method has a parameter onUpgrade that will be called when the database version is upgraded, in your case from 1 to 2, here you'll have to run additional sql commands to update your table. Something like this:
await openDatabase(path, version: 1, onCreate: _createDb, onUpgrade: (db, old, newVersion) async {
if(old < 2) {
await db.execute("ALTER TABLE task_table ADD link TEXT");
}
});
Also do not forget to update your create table statement to add your new column there.
One scenario would be that you don't want to save the link in the db, in this case you'll have to remove it from json serialization (your toMap method) .

The method was called on null even though method was already declared

I was making an app and it keeps showing an error the method was called on null. When I looked up for answers it was specified that this occurs when method is not declared but in my case method has been already declared.
Due to this error I am not able to save data in my app.
initialiseDatabase is the function it states as called on null.
Here is the code-
static DatabaseHelper _databaseHelper; // singleton
static Database _database;
String noteTable = 'note_Table';
String colId = 'id';
String colTitle = 'title';
String colDescription = 'description';
String colPriority = 'priority';
String colDate = 'date';
DatabaseHelper._createInstance();// named constructor to create dbms helper
factory DatabaseHelper(){
if(DatabaseHelper == null) {
_databaseHelper = DatabaseHelper._createInstance();
}
return _databaseHelper;
}
Future<Database> get database async{
if(_database == null){
_database = await initializeDatabase();
}
return _database;
}
Future<Database> initializeDatabase() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path + 'notes.db';
var notesDatabase = await openDatabase(path, version: 1, onCreate: _createDb);
return notesDatabase;
}
void _createDb(Database db, int newVersion) async{
await db.execute('CREATE TABLE $noteTable($colId INTEGER PRIMARY KEY AUTOINCREMENT, $colTitle TEXT.'
'$colDescription TEXT, $colPriority INTEGER, $colDate TEXT');
}
// Fetch Operation: Get all note objects from database
Future<List<Map<String, dynamic>>> getNoteMapList() async {
Database db = await this.database;
// var result = await db.rawQuery('SELECT * FROM $noteTable order by $colPriority ASC');
var result = await db.query(noteTable, orderBy: '$colPriority ASC');
return result;
}
// Insert Operation: Insert a Note object to database
Future<int> insertNote(Note note) async {
Database db = await this.database;
var result = await db.insert(noteTable, note.toMap());
return result;
}
// Update Operation: Update a Note object and save it to database
Future<int> updateNote(Note note) async {
var db = await this.database;
var result = await db.update(noteTable, note.toMap(), where: '$colId = ?', whereArgs: [note.id]);
return result;
}
// Delete Operation: Delete a Note object from database
Future<int> deleteNote(int id) async {
var db = await this.database;
int result = await db.rawDelete('DELETE FROM $noteTable WHERE $colId = $id');
return result;
}
// Get number of Note objects in database
Future<int> getCount() async {
Database db = await this.database;
List<Map<String, dynamic>> x = await db.rawQuery('SELECT COUNT (*) from $noteTable');
int result = Sqflite.firstIntValue(x);
return result;
}
// Get the 'Map List' [ List<Map> ] and convert it to 'Note List' [ List<Note> ]
Future<List<Note>> getNoteList() async {
var noteMapList = await getNoteMapList(); // Get 'Map List' from database
int count = noteMapList.length; // Count the number of map entries in db table
List<Note> noteList = List<Note>();
// For loop to create a 'Note List' from a 'Map List'
for (int i = 0; i < count; i++) {
noteList.add(Note.fromMapObject(noteMapList[i]));
}
return noteList;
}
}
While this is the function which it states as not declared
Future<Database> get database async{
if(_database == null){
_database = await initializeDatabase();
}
return _database;
}
Future<Database> initializeDatabase() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path + 'notes.db';
var notesDatabase = await openDatabase(path, version: 1, onCreate: _createDb);
return notesDatabase;
}

How to do CRUD operations on multiple tables in SQLite database in Flutter?

I am building a money budgeting app where the user can split their monthly salary in 5 areas: food, social, education, travel, savings. I have a register and log in screen. This is in Flutter/dart and I'm using sqlite.
Some of the data to store:
id, username, password, email, monthly_salary, food_initial, food_final, social_initial, social_final, education_initial, education_final, travel_initial, travel_final, savings_initial, savings_final
The 'initial' refers to a value that the user will input for themselves based on the division of the monthly salary. (ie. $5000 a month/5 containers = 1000 for each container. but, the user can edit this value of 1000 as their initial budgeted money). The 'final' refers to the user's remaining money (under the assumption they don't go over) for that container.
The initial and final values get reset at the end of the month. However, I would like to save their previous month's final values so the user can see a backlog of what they did.
I initially had 2 tables for my database. One was for the USER_DATA and the other was BUDGETS table. However, after struggling to figure out how to do CRUD operations for two tables, I decided to make it all into one table. But, after experiencing trouble with one table, I want to move back to more than one table. I'm confused now on:
1. How to use CRUD operations when having more than one table on DB?
2. Do I have to build a new model class in order to have more than one table?
3. How to save some of the user's data on database, but have to wait for the rest of the information to come in (later on while they're using the app)?
When making the constructor for the model class, and then referring to the model class in the UI, it requires me to bring in all of the parameters I have, but I don't have all of those values ready yet. The user still needs to register before they can input their salary and etc. Would I have to use the Future class to get over this hurdle?
I've watched a lot of videos on others building their databases in sqlite and with Flutter but all of them usually do a simple To-Do list app where they will need to fill in every column of the table and I haven't seen one yet that includes several tables. (ie. columns: id, description, priority, date)
--
I think have a good basis now on the UI side and using TextFormFields to access the information, but connecting the database/creating it properly is confusing me.
I am also considering writing the database in a .sql file now before proceeding. I have been teaching myself Flutter through tutorials (as background knowledge).
I know this is a bit long and all over the place, but I would greatly appreciate anyone who has experience with the sqlite environment in Flutter to please help me understand how to do this correctly.
Thank you. Also, if there is any more clarification/code needed, let me know.
Model class:
import 'dart:core';
class UserData {
//user table
int _userid;
String _username;
String _password;
String _email;
String _first_name;
String _last_name;
String _date;
int _month_id;
bool _subtract; //did the user subtract money from their funds? true/false
double _month_salary;
String _log_details;
/////////////budget table
double _edu_budget_initial;
double _edu_budget_final;
double _travel_budget_initial;
double _travel_budget_final;
double _living_budget_initial;
double _living_budget_final;
double _savings_budget_initial;
double _savings_budget_final;
double _social_budget_initial;
double _social_budget_final;
// using [___] around your user's data entry makes it optional in the table
// otherwise, these are all required fields
UserData(
this._username,
this._email,
this._first_name,
this._last_name,
this._password,
this._date,
this._month_id,
this._subtract,
this._month_salary,
this._log_details,
this._edu_budget_final,
this._edu_budget_initial,
this._living_budget_final,
this._living_budget_initial,
this._savings_budget_final,
this._savings_budget_initial,
this._social_budget_final,
this._social_budget_initial,
this._travel_budget_final,
this._travel_budget_initial);
//created a Named Constructor for the ability to create multiple constructors in one class
UserData.withId(
this._userid,
this._username,
this._password,
this._first_name,
this._last_name,
this._email,
this._date,
this._month_id,
this._subtract,
this._month_salary,
this._log_details,
this._edu_budget_final,
this._edu_budget_initial,
this._living_budget_final,
this._living_budget_initial,
this._savings_budget_final,
this._savings_budget_initial,
this._social_budget_final,
this._social_budget_initial,
this._travel_budget_final,
this._travel_budget_initial);
//UserData.budgetTable(this.date, this.month_id, this.log_details, this.edu_budget_final, this.edu_budget_initial, this.living_budget_final, this.living_budget_initial,
//this.month_salary, this.savings_budget_final, this.savings_budget_initial, this.social_budget_final,
//this.social_budget_initial, this.travel_budget_final, this.travel_budget_initial);
//getters:
//userdata table
int get userid => _userid;
String get username => _username;
String get password => _password;
String get email => _email;
String get firstname => _first_name;
String get lastname => _last_name;
String get date => _date;
//budget table
int get month_id => _month_id;
bool get subtract => _subtract;
double get month_salary => _month_salary;
String get log_details => _log_details;
double get living_budget_initial => _living_budget_initial;
double get living_budget_final => _living_budget_final;
double get social_budget_initial => _social_budget_initial;
double get social_budget_final => _social_budget_final;
double get edu_budget_initial => _edu_budget_initial;
double get edu_budget_final => _edu_budget_final;
double get travel_budget_initial => _travel_budget_initial;
double get travel_budget_final => _travel_budget_final;
double get savings_budget_initial => _savings_budget_initial;
double get savings_budget_final => _savings_budget_final;
//setters:
/*
set userid(int newUserID) {
//adding condition before storing what user put in
if (newUserID <= 12) {
this._userid = newUserID;
}
}
*/
set username(String newUsername) {
if (newUsername.length <= 30) {
this._username = newUsername;
}
}
set password(String newPassword) {
if (newPassword.length <= 30)
this._password = newPassword;
}
set email(String newEmail) {
if (newEmail.length <= 50)
this._email = newEmail;
}
set first_name(String newFirstName) {
if (newFirstName.length <= 30)
this._first_name = newFirstName;
}
set last_name(String newLastName) {
if (newLastName.length <= 30)
this._last_name = newLastName;
}
set month_id(int newMonthId) {
if (newMonthId <= 12) {
this._month_id = newMonthId;
}
}
set month_salary(double newMonthSalary) {
this._month_salary = newMonthSalary;
}
set date(String newDate) {
this._date = newDate;
}
set log_details(String newLogDetails) {
if (newLogDetails.length <= 255)
this._log_details = newLogDetails;
}
set subtract(bool newSubtract) {
this._subtract = newSubtract;
}
set living_budget_initial(double newLBI) {
if (newLBI <= 10) this._living_budget_initial = newLBI;
}
set living_budget_final(double newLBF) {
if (newLBF <= 10) this._living_budget_final = newLBF;
}
set social_budget_initial(double newSOBI) {
if (newSOBI <= 10) this._social_budget_initial = newSOBI;
}
set social_budget_final(double newSOBF) {
if (newSOBF <= 10) this._social_budget_final = newSOBF;
}
set edu_budget_initial(double newEBI) {
if (newEBI <= 10) this._edu_budget_initial = newEBI;
}
set edu_budget_final(double newEBF) {
if (newEBF <= 10) this._edu_budget_final = newEBF;
}
set travel_budget_initial(double newTBI) {
if (newTBI <= 10) this._travel_budget_initial = newTBI;
}
set travel_budget_final(double newTBF) {
if (newTBF <= 10) this._travel_budget_final = newTBF;
}
set savings_budget_initial(double newSBI) {
if (newSBI <= 10) this._savings_budget_initial = newSBI;
}
set savings_budget_final(double newSBF) {
if (newSBF <= 10) this._savings_budget_final = newSBF;
}
// converting object into Map objects
Map<String, dynamic> toMap() {
var map = Map<String, dynamic>();
var userid;
if (userid != null) {
map['userid'] = _userid;
}
map['userid'] = _userid;
map['username'] = _username;
map['password'] = _password;
map['email'] = _email;
map['first_name'] = _first_name;
map['last_name'] = _last_name;
//
map['month_id'] = _month_id;
map['month_salary'] = _month_salary;
map['date'] = _date;
map['log_details'] = _log_details;
map['subtract'] = _subtract;
map['living_budget_initial'] = _living_budget_initial;
map['living_budget_final'] = _living_budget_final;
map['social_budget_initial'] = _social_budget_initial;
map['social_budget_final'] = _social_budget_final;
map['edu_budget_initial'] = _edu_budget_initial;
map['edu_budget_final'] = _edu_budget_final;
map['travel_budget_initial'] = _travel_budget_initial;
map['travel_budget_final'] = _travel_budget_final;
map['savings_budget_initial'] = _savings_budget_initial;
map['savings_budget_final'] = _savings_budget_final;
return map;
}
//converts map objects into objects
UserData.fromMapObject(Map<String, dynamic> map) {
this._userid = map['userid'];
this._username = map['username'];
this._password = map['password'];
this._email = map['email'];
this.first_name = map['first_name'];
this.last_name = map['last_name'];
//
this._month_id = map['month_id'];
this._month_salary = map['month_salary'];
this._date = map['date'];
this._log_details = map['log_details'];
this._subtract = map['subtract'];
this._living_budget_initial = map['living_budget_initial'];
this._living_budget_final = map['living_budget_final'];
this._social_budget_initial = map['social_budget_initial'];
this._social_budget_final = map['social_budget_final'];
this._edu_budget_initial = map['edu_budget_initial'];
this._edu_budget_final = map['edu_budget_final'];
this._travel_budget_initial = map['travel_budget_initial'];
this._travel_budget_final = map['travel_budget_final'];
this._savings_budget_initial = map['savings_budget_initial'];
this._savings_budget_final = map['savings_budget_final'];
}
}
Database helper class:
import 'package:sqflite/sqflite.dart';
import 'dart:async';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:jewell_1/user_data.dart';
class DbHelper {
// Create a private instance of the class
static final DbHelper _dbhelper = new DbHelper._internal();
String DB_name = "user_data.db";
static final int DATABASE_VERSION = 2;
String userDataTable = 'user_data_table';
String colUserId = 'userid';
String colUsername = 'username';
String colPassword = 'password';
String colEmail = 'email';
String colFirstName = 'first_name';
String colLastName = 'last_name';
String colDate = 'date';
String colMonthId = 'month_id';
String colSubtract = 'subtract';
String colMonthSalary = 'month_salary';
String colLogDetails = 'log_details';
String colLBI = 'living_budget_initial';
String colLBF = 'living_budget_final';
String colSOBI = 'social_budget_initial';
String colSOBF = 'social_budget_final';
String colEBI = 'edu_budget_initial';
String colEBF = 'edu_budget_final';
String colTBI = 'travel_budget_initial';
String colTBF = 'travel_budget_final';
String colSBI = 'savings_budget_initial';
String colSBF = 'savings_budget_final';
// Create an empty private named constructor
DbHelper._internal();
// Use the factory to always return the same instance
factory DbHelper() {
return _dbhelper;
}
static Database _db;
Future<Database> get db async {
if (_db == null) {
_db = await initializeDb();
}
return _db;
}
Future<Database> initializeDb() async {
Directory dir = await getApplicationDocumentsDirectory();
String path = dir.path + "todos.db";
var dbTodos = await openDatabase(path, version: DATABASE_VERSION, onCreate: _createDb);
return dbTodos;
}
void _createDb(Database db, int newVersion) async {
await db.execute(
"CREATE TABLE $userDataTable($colUserId INETEGER PRIMARY KEY, $colUsername TEXT," +
"$colPassword TEXT, $colEmail TEXT, $colFirstName TEXT,"
"$colLastName TEXT, $colDate TEXT, $colMonthId INTEGER,"
" $colSubtract BOOLEAN, $colMonthSalary DOUBLE, $colLogDetails TEXT,"
" $colEBI DOUBLE, $colEBF DOUBLE, $colTBI DOUBLE, $colTBF DOUBLE, "
" $colLBI DOUBLE, $colLBF DOUBLE, $colSBI DOUBLE, $colSBF DOUBLE,"
" $colSOBI DOUBLE, $colSOBF DOUBLE)");
}
Future<int> insertData(UserData data) async {
Database db = await this.db;
var result = await db.insert(userDataTable, data.toMap());
return result;
}
Future<List> getDatas() async {
Database db = await this.db;
var result =
await db.rawQuery("SELECT * FROM $userDataTable order by $colUserId ASC");
return result;
}
Future<int> getCount() async {
Database db = await this.db;
var result = Sqflite.firstIntValue(
await db.rawQuery("SELECT COUNT (*) FROM $userDataTable"));
return result;
}
Future<int> updateData(UserData data) async {
var db = await this.db;
var result = await db
.update(userDataTable, data.toMap(), where: "$colUserId=?", whereArgs: [data.userid]);
return result;
}
Future<int> deleteData(int id) async {
int result;
var db = await this.db;
result = await db.rawDelete("DELETE FROM $userDataTable WHERE $colUserId=$id");
return result;
}
}
To be more specific, I am confused on not writing the query of a new table, but rather at this point:
var result = await db.insert(userDataTable, data.toMap());
return result;
The result is only containing my userDataTable and if I create another table, then am I supposed to add another var result? I tried to have:
var result2 = await db.insert(budgetsTable, data.toMap());
This seemed wrong. Also, I didn't know how to return both results.
That was specifically where/when I started to scavenge the internet of people who have made CRUD operations using more than one table on sqlite with Flutter.

How to create multiple table in Sqlite database at different times in Flutter

So Initially I created a table named "TABLE" in the database. I wanted to add another table. So I added another query to create a table. However I get an error saying "TABLE1 does not exist" when I run the app.
I do feel like there is a flaw in my code. I think the _onCreate() method will only be called the first time I run the app. So any code I add on _onCreate() method afterwards will not run. Any help will be appreciated.
class DBHelper {
static Database _db;
static const String DB_NAME = 'employeeDB';
static const String ID = 'id';
static const String NAME = 'name';
static const String TABLE = 'Employee';
static const String ID1 = 'id1';
static const String NAME1 = 'name1';
static const String TABLE1 = 'Employee1';
Future<Database> get db async {
if (_db != null) {
return _db;
}
_db = await initDb();
return _db;
}
initDb() async {
io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, DB_NAME);
var db = await openDatabase(path, version: 1, onCreate: _onCreate);
return db;
}
_onCreate(Database db, int version) async {
await db.execute("CREATE TABLE $TABLE ($ID INTEGER PRIMARY KEY,$NAME TEXT)");
await db.execute("CREATE TABLE $TABLE1 ($ID1 INTEGER PRIMARY KEY,$NAME1 TEXT)");
}
Future<Employee> save(Employee employee) async {
var dbClient = await db;
employee.id = await dbClient.insert(TABLE, employee.toMap());
return employee;
}
Future<Employee1> saveEmp1(Employee1 employee) async {
var dbClient = await db;
employee.id = await dbClient.insert(TABLE1, employee.toMap());
return employee;
}
Future<List<Employee>> getEmployees() async {
var dbClient = await db;
List<Map> maps = await dbClient.query(TABLE, columns: [ID, NAME]);
List<Employee> employees = [];
if (maps.length > 0) {
for (int i = 0; i < maps.length; i++) {
employees.add(Employee.fromMap(maps[i]));
}
}
return employees;
}
Future<List<Employee1>> getEmployees1() async {
var dbClient = await db;
List<Map> maps = await dbClient.query(TABLE1, columns: [ID1,
NAME1]);
List<Employee1> employees = [];
if (maps.length > 0) {
for (int i = 0; i < maps.length; i++) {
employees.add(Employee.fromMap(maps[i]));
}
}
return employees;
}
}
The first time run this app and initDb() in emulator, the db file employeeDB has created.
and it will not be created again
For only test app execution,
you can change
String DB_NAME = 'employeeDB'
to another name
String DB_NAME = 'employeeDB1'
or you can uninstall this app from Emulator first then run it again.
source code snippet of https://github.com/tekartik/sqflite/blob/master/sqflite/lib/sqlite_api.dart
/// Called when the database is created.
OnDatabaseCreateFn onCreate;
For schema migration, you can use OnUpgrade, detail reference https://efthymis.com/migrating-a-mobile-database-in-flutter-sqlite/
code snippet
await openDatabase(path,
version: 1,
onCreate: (Database db, int version) async {
await db.execute(initialSchema));
},
onUpgrade: (Database db, int oldVersion, int newVersion) async {
await db.execute(migrationScript));
});
You have to create migrations and run them against your existing database using the onUpgrade handler. Basically you need to check the existing database version and upgrade if the version is smaller than the migration number.
You can check out the detail steps/code tutorial here.
I needed to create more than just multiple tables; but multiple database. I have since developed a dart package; sqlite_at_runtime that stretches to as far as creating all these entities at run time.
Below is an example code that creates three tables with similar attributes.
await Sqlartime.tableCreate(['sample1','sample2','sample3'],['name TEXT','age INTEGER','temp REAL']);

Resources