SoFunction
Updated on 2025-04-10

How to use Flutter database

illustrate

Flutter natively does not support database operations, it uses SQLlit plug-in to enable applications to use databases. In fact, Flutter communicates with the native system through plug-ins to perform database operations.

Platform support

  • FLutter's SQLite plugin supports IOS, Android, and MacOS platforms
  • If you want to support Linux/Windows/DartVM, use sqflite_common_ffi
  • No web platform supported
  • Database operations are executed in the background of Android or iOS

Use Cases

notepad_sqflite Simple Notepad app that can run on iOS/Android/Windows/linux/Mac

Simple use

Add dependencies

In order to use SQLite database, you need to import the two packages: sqflite and path

  • sqflite provides a wealth of classes and methods so that you can easily and practically use SQLite databases.
  • path provides a number of ways so that you can correctly define where the database is stored on disk.
dependencies:
  sqflite: ^1.3.0
  path:Version number

use

Import

import 'dart:async';

import 'package:path/';
import 'package:sqflite/';

Open the database
SQLite database is a file in the file system. If it is a relative path, the path is the path obtained by getDatabasesPath(), which is associated with the default database directory on Android and the documents directory on iOS.

var db = await openDatabase('my_db.db');

Many times we don't need to manually close the database when we use it, because the database will be closed when the program is closed. If you want to automatically release resources, you can use the following method:

await ();

Execute the original SQL query

Use getDatabasesPath() to get the database location

Use the getDatabasesPath method in the sqflite package and use the join method in the path package to define the path to the database. Using the join method in the path package is a best practice to ensure the correctness of each platform path.

var databasesPath = await getDatabasesPath();
String path = join(databasesPath, '');

Open the database

Database database = await openDatabase(path, version: 1,
    onCreate: (Database db, int version) async {
  // Create tables when creating database  await (
      'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)');
});

increase

Insert several pieces of data into a table in a transaction

await ((txn) async {
  int id1 = await (
      'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)');
  print('inserted1: $id1');
  int id2 = await (
      'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)',
      ['another name', 12345678, 3.1416]);
  print('inserted2: $id2');
});

delete

Delete a data in the table

count = await database
    .rawDelete('DELETE FROM Test WHERE name = ?', ['another name']);

change

Modify the data in the table

int count = await ('UPDATE Test SET name = ?, value = ? WHERE name = ?',
    ['updated name', '9876', 'some name']);
print('updated: $count');

check

Query the data in the table

// Get the records
List<Map> list = await ('SELECT * FROM Test');
List<Map> expectedList = [
  {'name': 'updated name', 'id': 1, 'value': 9876, 'num': 456.789},
  {'name': 'another name', 'id': 2, 'value': 12345678, 'num': 3.1416}
];
print(list);
print(expectedList);

Total number of data stored in the query table

count = (await ('SELECT COUNT(*) FROM Test'));

Close the database

await ();

Delete the database

await deleteDatabase(path);

Using SQL Assistant

Create fields and associated classes in tables

//Fieldfinal String tableTodo = 'todo';
final String columnId = '_id';
final String columnTitle = 'title';
final String columnDone = 'done';

//Responsive Classclass Todo {
  int id;
  String title;
  bool done;

  //Convert the current class to a map for external use  Map&lt;String, Object?&gt; toMap() {
    var map = &lt;String, Object?&gt;{
      columnTitle: title,
      columnDone: done == true ? 1 : 0
    };
    if (id != null) {
      map[columnId] = id;
    }
    return map;
  }
  //No parametric structure  Todo();
  
  //Convert map type data into the constructor of the current class object.  (Map&lt;String, Object?&gt; map) {
    id = map[columnId];
    title = map[columnTitle];
    done = map[columnDone] == 1;
  }
}

Use the above class to create and delete databases and add, delete, modify and search data.

class TodoProvider {
  Database db;

  Future open(String path) async {
    db = await openDatabase(path, version: 1,
        onCreate: (Database db, int version) async {
      await ('''
  create table $tableTodo ( 
  $columnId integer primary key autoincrement, 
  $columnTitle text not null,
  $columnDone integer not null)
                        ''');
    });
  }

  //Insert a piece of data into the table. If it has been inserted, replace the previous one.  Future&lt;Todo&gt; insert(Todo todo) async {
     = await (tableTodo, (),conflictAlgorithm: ,);
    return todo;
  }

  Future&lt;Todo&gt; getTodo(int id) async {
    List&lt;Map&gt; maps = await (tableTodo,
        columns: [columnId, columnDone, columnTitle],
        where: '$columnId = ?',
        whereArgs: [id]);
    if ( &gt; 0) {
      return ();
    }
    return null;
  }

  Future&lt;int&gt; delete(int id) async {
    return await (tableTodo, where: '$columnId = ?', whereArgs: [id]);
  }

  Future&lt;int&gt; update(Todo todo) async {
    return await (tableTodo, (),
        where: '$columnId = ?', whereArgs: []);
  }

  Future close() async =&gt; ();
}

= Query all data in the table

List<Map<String, Object?>> records = await ('my_table');

Get the first piece of data in the result

Map<String, Object?> mapRead = ;

The Map in the list of query results above is read-only data. Modifying this data will throw an exception

mapRead['my_column'] = 1;
// Crash... `mapRead` is read-only

Create a copy of the map and modify the fields in it

// Create a map copy based on the above mapMap&lt;String, Object?&gt; map = Map&lt;String, Object?&gt;.from(mapRead);
// Modify the field value stored in this copy in memorymap['my_column'] = 1;

Convert the query List<map> data into List<Todo> type, so that we can use it happily.

// Convert the List<Map<String, dynamic> into a List<Todo>.
  return (, (i) {
    return Todo(
      id: maps[i][columnId],
      title: maps[i][columnTitle],
      done: maps[i][columnDown],
    );
  });

Batch processing

You can use batch processing to avoid frequent interactions between dart and native.

batch = ();
('Test', {'name': 'item'});
('Test', {'name': 'new_item'}, where: 'name = ?', whereArgs: ['item']);
('Test', where: 'name = ?', whereArgs: ['item']);
results = await ();

Getting the results of each operation is costly (inserted Ids and the number of changes to be updated and deleted). If you don't care about the results of the operation, you can perform the following operations to close the response of the result

await (noResult: true);

Use batch processing in transactions

Batch operations are performed in a transaction, and batch processing will not be submitted after the transaction is committed.

await ((txn) async {
  var batch = ();
  
  // ...
  
  // commit but the actual commit will happen when the transaction is committed
  // however the data is available in this transaction
  await ();
  
  //  ...
});

Batch exceptions are ignored

By default, an error will stop in batch processing once an error occurs (unexecuted statements will not be executed). You can ignore the error so that subsequent operations can continue to be executed.

await (continueOnError: true);

About table and column names

Normally we should avoid using SQLite keywords to name table names and column names. like:

"add","all","alter","and","as","autoincrement","between","case","check","collate",
"commit","constraint","create","default","deferrable","delete","distinct","drop",
"else","escape","except","exists","foreign","from","group","having","if","in","index",
"insert","intersect","into","is","isnull","join","limit","not","notnull","null","on",
"or","order","primary","references","select","set","table","then","to","transaction",
"union","unique","update","using","values","when","where"

Supported storage types

  • As value has not been validated, avoid unsupported types. See:
  • DateTime type is not supported, it can be stored as int or String
  • Bool type is not supported, it can be stored as int type 0:false, 1:true

SQLite type dart type Value range
integer int From -2^63 to 2^63-1
real num
text String
blob Uint8List

refer to

sqflile official address
flutter official introduction document for using SQLite for data storage

This is the end of this article about how to use Flutter database. For more related content on using Flutter database, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!