Skip to main content
Flutter Basics – Complete Beginner to Advanced Guide
CHAPTER 21 Beginner

SQLite Database in Flutter

Updated: May 16, 2026
35 min read

# CHAPTER 21

SQLite Database in Flutter

1. Introduction

Shared Preferences works perfectly for a username or a high score. But what if you are building an offline Notes app, an Expense Tracker, or a robust To-Do list? You need to sort items by date, filter them by category, and update thousands of records instantly. You need a real database. In this chapter, we will master the SQLite Database in Flutter. We will install the powerful sqflite package to embed a fully functional SQL relational database directly into the user's phone, allowing us to perform high-speed offline CRUD (Create, Read, Update, Delete) operations.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Install the sqflite and path packages.
  • Initialize an embedded SQLite database.
  • Create SQL tables with primary keys and data types.
  • Execute raw SQL queries or use built-in helper methods.
  • Perform CRUD operations (Insert, Query, Update, Delete).

3. Setup and Installation

To work with SQLite, you need two packages. Add them to pubspec.yaml:
yaml
123
dependencies:
  sqflite: ^2.3.0
  path: ^1.8.3 # Required to find the correct hard drive directory on iOS/Android

4. Creating the Database Helper

Because opening a database connection is an expensive, asynchronous operation, we create a Singleton class called DatabaseHelper. This ensures the app only opens the database once, and reuses that connection everywhere.
dart
1234567891011121314151617181920212223242526272829303132333435
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class DatabaseHelper {
  // 1. Setup the Singleton
  static final DatabaseHelper instance = DatabaseHelper._init();
  static Database? _database;
  DatabaseHelper._init();

  // 2. Open the Database
  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDB(&#039;notes.db');
    return _database!;
  }

  Future<Database> _initDB(String filePath) async {
    final dbPath = await getDatabasesPath();
    final path = join(dbPath, filePath);

    // 3. Create the Database and Tables
    return await openDatabase(path, version: 1, onCreate: _createDB);
  }

  Future _createDB(Database db, int version) async {
    // Write RAW SQL to create a table!
    await db.execute(&#039;''
      CREATE TABLE notes (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        title TEXT NOT NULL,
        content TEXT NOT NULL
      )
    &#039;'');
  }
}

5. Performing CRUD Operations

Once the table is created, we write methods inside our DatabaseHelper to interact with it.

CREATE (Insert):

dart
12345
Future<int> insertNote(Map<String, dynamic> row) async {
  Database db = await instance.database;
  // Automatically writes the INSERT INTO SQL command!
  return await db.insert(&#039;notes', row); 
}

READ (Query):

dart
12345
Future<List<Map<String, dynamic>>> getAllNotes() async {
  Database db = await instance.database;
  // Automatically writes SELECT * FROM notes!
  return await db.query(&#039;notes'); 
}

UPDATE:

dart
12345
Future<int> updateNote(Map<String, dynamic> row) async {
  Database db = await instance.database;
  int id = row[&#039;id'];
  return await db.update(&#039;notes', row, where: 'id = ?', whereArgs: [id]);
}

DELETE:

dart
1234
Future<int> deleteNote(int id) async {
  Database db = await instance.database;
  return await db.delete(&#039;notes', where: 'id = ?', whereArgs: [id]);
}

6. Integrating with the UI

When the screen opens, you fetch the notes and display them. Because getAllNotes returns a Future, you can use setState to update the UI once the data arrives from the database.
dart
12345678910111213141516171819202122232425262728
List<Map<String, dynamic>> myNotes = [];

@override
void initState() {
  super.initState();
  refreshNotes();
}

Future<void> refreshNotes() async {
  final data = await DatabaseHelper.instance.getAllNotes();
  setState(() {
    myNotes = data; // UI redraws with the database contents!
  });
}

// Inside the build method:
ElevatedButton(
  onPressed: () async {
    // 1. Insert data into DB
    await DatabaseHelper.instance.insertNote({
      &#039;title': 'Buy Groceries',
      &#039;content': 'Milk, Eggs, Bread'
    });
    // 2. Refresh the UI
    refreshNotes();
  },
  child: Text("Add Note"),
)

7. Visual Learning: Local vs Cloud

txt
123456789101112
[ SQFLITE (Offline App) ]               [ FIREBASE/API (Online App) ]

User Device:                            User Device:
+-------------+                         +-------------+
| UI Widget   |                         | UI Widget   |
|     v       |                         |     v       |
| SQFLite DB  |                         | Internet    |
| (100% Free) |                         |     v       |
+-------------+                         | Server DB   |
                                        +-------------+
Pros: Lightning fast, no internet.      Pros: Synced across multiple devices.
Cons: Data lost if phone is destroyed.  Cons: Slower, requires Wi-Fi.

8. Common Mistakes

  • SQL Injection Vulnerabilities: Notice in the Update/Delete methods we used where: 'id = ?', whereArgs: [id]. Beginners often try to manually concatenate strings: where: 'id = $id'. NEVER DO THIS. If a user types malicious SQL code into a text box, string concatenation will execute it and delete your entire database. ALWAYS use the ? parameters (whereArgs), which securely sanitizes the input!

9. Best Practices

  • Use Model Classes: Just like we did with JSON parsing in Chapter 19, you should never pass raw Maps to your UI. Create a Note class with fromMap() and toMap() methods. Your getAllNotes method should return a List<Note>, ensuring your UI is strictly typed and protected from typo crashes.

10. Practice Exercises

  1. 1. What official package allows you to embed a relational SQL database directly into a Flutter application?
  1. 2. Write the raw SQL statement required to create a table named users with an id (integer) and name (text).

11. MCQs with Answers

Question 1

When creating a DatabaseHelper class in Dart to manage a local database, why is the "Singleton" pattern (having a private constructor and a single static instance) universally recommended?

Question 2

When executing an update or delete query in sqflite, what is the purpose of the whereArgs: [id] property?

12. Interview Questions

  • Q: Explain the necessity of the path package when configuring sqflite. Why can't a developer simply hardcode a file path like C:/app/database.db?
  • Q: Describe the security risks of manually concatenating variables into SQL strings. How does sqflite mitigate this risk through parameterized queries?
  • Q: Compare the architectural use cases of shared_preferences versus sqflite. Provide a specific app feature that mandates the use of sqflite.

13. FAQs

Q: Can I view my SQLite database file visually? A: Yes! On the Android Emulator, you can use Android Studio's "Device File Explorer" to navigate to data/data/com.yourcompany.yourapp/databases/, download the .db file, and open it with a free visual tool like "DB Browser for SQLite".

14. Summary

In Chapter 21, we brought robust offline capabilities to our application. We installed the sqflite package, securely locating the correct device directory using the path package. We architected a Singleton DatabaseHelper to efficiently manage a single open connection, wrote raw SQL to generate our tables, and executed parameterized queries to safely perform CRUD operations without exposing the app to SQL injection attacks. Our app can now store and query massive datasets entirely offline.

15. Next Chapter Recommendation

Offline data is fast and secure, but what if a user wants to log in on their iPad and see the same notes they typed on their iPhone? We need a cloud backend. Proceed to Chapter 22: Firebase Integration in Flutter.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·