--- title: Importing and exporting databases description: Using drift with an existing database --- You can use drift with a pre-propulated database that you ship with your app. This page also describes how to export the underlying sqlite3 database used by drift into a file. ## Using an existing database You can use a `LazyDatabase` wrapper to run an asynchronous computation before drift opens a database. This is a good place to check if the target database file exists, and, if it doesnt, create one. This example shows how to do that from assets. ### Including the database First, create the sqlite3 database you want to ship with your app. You can create a database with the [sqlite3 CLI tool](https://sqlite.org/cli.html) on your development machine. Of course, you can also create the database programmatically by using a library like [sqlite3](https://pub.dev/packages/sqlite3) (or even drift itself). To ship that database to users, you can include it as a [flutter asset](https://flutter.dev/docs/development/ui/assets-and-images). Simply include it in your pubspec: ```yaml flutter: assets: - assets/my_database.db ``` ### Extracting the database To initialize the database before using drift, you need to extract the asset from your app onto the device. ```dart import 'package:drift/drift.dart'; import 'package:flutter/services.dart' show rootBundle; import 'package:path/path.dart' as p; import 'package:sqlite3/sqlite3.dart'; import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart'; LazyDatabase _openConnection() { return LazyDatabase(() async { // put the database file, called db.sqlite here, into the documents folder // for your app. final dbFolder = await getApplicationDocumentsDirectory(); final file = File(p.join(dbFolder.path, 'app.db')); if (!await file.exists()) { // Extract the pre-populated database file from assets final blob = await rootBundle.load('assets/my_database.db'); final buffer = blob.buffer; await file.writeAsBytes(buffer.asUint8List(blob.offsetInBytes, blob.lengthInBytes)); } // Also work around limitations on old Android versions if (Platform.isAndroid) { await applyWorkaroundToOpenSqlite3OnOldAndroidVersions(); } // Make sqlite3 pick a more suitable location for temporary files - the // one from the system may be inaccessible due to sandboxing. final cachebase = (await getTemporaryDirectory()).path; // We can't access /tmp on Android, which sqlite3 would try by default. // Explicitly tell it about the correct temporary directory. sqlite3.tempDirectory = cachebase; return NativeDatabase.createInBackground(file); }); } ``` In drift, you can use a [LazyDatabase](https://pub.dev/documentation/drift/latest/drift/LazyDatabase-class.html) to perform that work just before your drift database is opened: !!! warning This snippet only works on native platforms. See [existing databases on the web](../platforms/web.md#using-existing-databases) for web support. Finally, use that method to open your database: ```dart @DriftDatabase(tables: [Todos, Categories]) class MyDatabase extends _$MyDatabase { MyDatabase() : super(_openConnection()); // ... ``` ### Additional considerations for WAL When enabling [write-ahead logging](https://www.sqlite.org/wal.html), sqlite3 won't immediately store all writes in the main database file. Instead, additional `-wal` and `-shm` files are created to append new writes that are then periodically synced into the main database file. Restoring a WAL database requires copying the `-wal` file as well. When overwriting an existing WAL database on the device with a database using a different journaling mode, the `-wal` file should be deleted too. ## Exporting a database To export a sqlite3 database into a file, you can use the `VACUUM INTO` statement. Inside your database class, this could look like the following: ```dart Future exportInto(File file) async { // Make sure the directory of the target file exists await file.parent.create(recursive: true); // Override an existing backup, sqlite expects the target file to be empty if (file.existsSync()) { file.deleteSync(); } await customStatement('VACUUM INTO ?', [file.path]); } ``` You can now export this file containing the database of your app with another package like `flutter_share` or other backup approaches. To import a database file into your app's database at runtime, you can use the following approach: 1. Use the `sqlite3` package to open the backup database file. 2. Run the `VACUUM INTO ?` statement on the backup database, targeting the path of your application's database (the one you pass to `NativeDatabase`). The [example app](https://github.com/simolus3/drift/blob/96b3947fc16de99ffe25bcabc124e3b3a7c69571/examples/app/lib/screens/backup/supported.dart#L47-L68) in the drift repository also has an example for a working backup/restore functionality.