1---
2title: SQLite
3description: A library that provides access to a database that can be queried through a WebSQL-like API.
4sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-sqlite'
5packageName: 'expo-sqlite'
6---
7
8import APISection from '~/components/plugins/APISection';
9import { APIInstallSection } from '~/components/plugins/InstallSection';
10import PlatformsSection from '~/components/plugins/PlatformsSection';
11import { Terminal } from '~/ui/components/Snippet';
12import { Step } from '~/ui/components/Step';
13import { BoxLink } from '~/ui/components/BoxLink';
14import { GithubIcon } from '@expo/styleguide-icons';
15
16`expo-sqlite` gives your app access to a database that can be queried through a [WebSQL](https://www.w3.org/TR/webdatabase/)-like API. The database is persisted across restarts of your app.
17
18<PlatformsSection android emulator ios simulator />
19
20## Installation
21
22<APIInstallSection />
23
24## Usage
25
26<BoxLink
27  title="To-do list app"
28  description="An example to-do list app is available that uses this module for storage."
29  href="https://github.com/expo/examples/tree/master/with-sqlite"
30  Icon={GithubIcon}
31/>
32
33### Importing an existing database
34
35To open a new SQLite database using an existing `.db` file you already have, follow the steps below:
36
37<Step label="1">
38Install `expo-file-system` and `expo-asset` modules:
39
40<Terminal cmd={['$ npx expo install expo-file-system expo-asset']} />
41
42</Step>
43
44<Step label="2">
45Create a **metro.config.js** file at the root of your project with the following contents to include [extra asset extensions](/guides/customizing-metro/#adding-more-file-extensions-to--assetexts):
46
47```js
48const { getDefaultConfig } = require('expo/metro-config');
49
50const defaultConfig = getDefaultConfig(__dirname);
51
52defaultConfig.resolver.assetExts.push('db');
53
54module.exports = defaultConfig;
55```
56
57</Step>
58
59<Step label="3">
60
61Use the following function (or similar) to open your database:
62
63```ts
64async function openDatabase(pathToDatabaseFile: string): Promise<SQLite.WebSQLDatabase> {
65  if (!(await FileSystem.getInfoAsync(FileSystem.documentDirectory + 'SQLite')).exists) {
66    await FileSystem.makeDirectoryAsync(FileSystem.documentDirectory + 'SQLite');
67  }
68  await FileSystem.downloadAsync(
69    Asset.fromModule(require(pathToDatabaseFile)).uri,
70    FileSystem.documentDirectory + 'SQLite/myDatabaseName.db'
71  );
72  return SQLite.openDatabase('myDatabaseName.db');
73}
74```
75
76</Step>
77
78### Executing statements with an async transaction
79
80```js
81const db = SQLite.openDatabase('dbName', version);
82
83const readOnly = true;
84await db.transactionAsync(async tx => {
85  const result = await tx.executeSqlAsync('SELECT COUNT(*) FROM USERS', []);
86  console.log('Count:', result.rows[0]['COUNT(*)']);
87}, readOnly);
88```
89
90### Executing statements outside of a transaction
91
92> You should use this kind of execution only when it is necessary. For instance, when code is a no-op within transactions. Example: `PRAGMA foreign_keys = ON;`.
93
94```js
95const db = SQLite.openDatabase('dbName', version);
96
97await db.execAsync([{ sql: 'PRAGMA foreign_keys = ON;', args: [] }], false);
98console.log('Foreign keys turned on');
99```
100
101## API
102
103```js
104import * as SQLite from 'expo-sqlite';
105```
106
107<APISection packageName="expo-sqlite" apiName="SQLite" />
108