Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do a database insert with SQFlite in Flutter

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.

like image 894
Suragch Avatar asked Jan 08 '19 18:01

Suragch


People also ask

How do you insert data into sqflite in Flutter?

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.

How do you add data to a database in Flutter?

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.


1 Answers

Add the dependencies

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.

Make a database helper class

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
          )
          ''');
  }
}

Insert data

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

  • You will have to import the DatabaseHelper class and sqflite if you are in another file (like main.dart).
  • The SQFlite plugin uses a Map<String, dynamic> to map the column names to the data in each row.
  • We didn't specify the id. SQLite auto increments it for us.

Raw insert

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]);

Supplemental code

enter image description here

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));
  }

}

Going on

  • This post is a development from my previous post: Simple SQFlite database example in Flutter. See that post for other SQL operations and advice.
like image 113
Suragch Avatar answered Oct 17 '22 01:10

Suragch