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