How do you insert data into a database in Flutter using the SQFlite plugin?
There are a number of problem solving questions out there but none that I could find to add a canonical answer to. My answer is below.
To insert the data or model inside the database we use the insert method. It takes a table name and JSON value. To fetch the data from the database we use the query method. this method takes the name of the table that is needed to be fetched.
We can easily insert data in SQLite database with the help of sqflite plugin in Flutter. With the help of SQLite database in accordance with future, await, and async we can insert, retrieve, update, or delete data in Flutter.
Open pubspec.yaml
and in the dependency section add the following lines:
sqflite: ^1.0.0
path_provider: ^0.4.1
The sqflite
is the SQFlite plugin of course and the path_provider
will help us get the user directory on Android and iPhone.
I'm keeping a global reference to the database in a singleton class. This will prevent concurrency issues and data leaks (that's what I hear, but tell me if I'm wrong). You can also add helper methods (like insert) in here for accessing the database.
Create a new file called database_helper.dart and paste in the following code:
import 'dart:io' show Directory;
import 'package:path/path.dart' show join;
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart' show getApplicationDocumentsDirectory;
class DatabaseHelper {
static final _databaseName = "MyDatabase.db";
static final _databaseVersion = 1;
static final table = 'my_table';
static final columnId = '_id';
static final columnName = 'name';
static final columnAge = 'age';
// make this a singleton class
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
// only have a single app-wide reference to the database
static Database _database;
Future<Database> get database async {
if (_database != null) return _database;
// lazily instantiate the db the first time it is accessed
_database = await _initDatabase();
return _database;
}
// this opens the database (and creates it if it doesn't exist)
_initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
return await openDatabase(path,
version: _databaseVersion,
onCreate: _onCreate);
}
// SQL code to create the database table
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
$columnId INTEGER PRIMARY KEY,
$columnName TEXT NOT NULL,
$columnAge INTEGER NOT NULL
)
''');
}
}
We'll use an async method to do our insert:
_insert() async {
// get a reference to the database
// because this is an expensive operation we use async and await
Database db = await DatabaseHelper.instance.database;
// row to insert
Map<String, dynamic> row = {
DatabaseHelper.columnName : 'Bob',
DatabaseHelper.columnAge : 23
};
// do the insert and get the id of the inserted row
int id = await db.insert(DatabaseHelper.table, row);
// show the results: print all rows in the db
print(await db.query(DatabaseHelper.table));
}
Notes
DatabaseHelper
class and sqflite
if you are in another file (like main.dart).Map<String, dynamic>
to map the column names to the data in each row.id
. SQLite auto increments it for us.SQFlite also supports doing a raw insert. This means that you can use a SQL string. Lets insert the same row again using rawInsert()
.
db.rawInsert('INSERT INTO my_table(name, age) VALUES("Bob", 23)');
Of course, we wouldn't want to hard code those values into the SQL string, but we also wouldn't want to use interpelation like this:
String name = 'Bob';
int age = 23;
db.rawInsert('INSERT INTO my_table(name, age) VALUES($name, $age)'); // Dangerous!
That would open us up to SQL injection attacks. Instead we can use data binding like this:
db.rawInsert('INSERT INTO my_table(name, age) VALUES(?, ?)', [name, age]);
The [name, age]
are filled in for the question mark placeholders in (?, ?)
. The table and column names are safer to use interpelation for, so we could do this finally:
String name = 'Bob';
int age = 23;
db.rawInsert(
'INSERT INTO ${DatabaseHelper.table}'
'(${DatabaseHelper.columnName}, ${DatabaseHelper.columnAge}) '
'VALUES(?, ?)', [name, age]);
For your copy-and-paste convenience, here is the layout code for main.dart
:
import 'package:flutter/material.dart';
import 'package:flutter_db_operations/database_helper.dart';
import 'package:sqflite/sqflite.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SQFlite Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('sqflite'),
),
body: RaisedButton(
child: Text('insert', style: TextStyle(fontSize: 20),),
onPressed: () {_insert();},
),
);
}
_insert() async {
// get a reference to the database
// because this is an expensive operation we use async and await
Database db = await DatabaseHelper.instance.database;
// row to insert
Map<String, dynamic> row = {
DatabaseHelper.columnName : 'Bob',
DatabaseHelper.columnAge : 23
};
// do the insert and get the id of the inserted row
int id = await db.insert(DatabaseHelper.table, row);
// raw insert
//
// String name = 'Bob';
// int age = 23;
// int id = await db.rawInsert(
// 'INSERT INTO ${DatabaseHelper.table}'
// '(${DatabaseHelper.columnName}, ${DatabaseHelper.columnAge}) '
// 'VALUES(?, ?)', [name, age]);
print(await db.query(DatabaseHelper.table));
}
}
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