Expo SQLite iconExpo SQLite

GitHub

npm

A library that provides access to a database that can be queried through a SQLite API.

Android
iOS
macOS

expo-sqlite gives your app access to a database that can be queried through a SQLite API. The database is persisted across restarts of your app.

Installation

Terminal
npx expo install expo-sqlite

If you are installing this in an existing React Native app, start by installing expo in your project. Then, follow the additional instructions as mentioned by the library's README under "Installation in bare React Native projects" section.

Configuration in app.json/app.config.js

You can configure expo-sqlite for advanced configurations using its built-in config plugin if you use config plugins in your project (EAS Build or npx expo run:[android|ios]). The plugin allows you to configure various properties that cannot be set at runtime and require building a new app binary to take effect.

Example app.json with config plugin

app.json
{
  "expo": {
    "plugins": [
      [
        "expo-sqlite",
        {
          "enableFTS": true,
          "useSQLCipher": true,
          "android": {
            // Override the shared configuration for Android
            "enableFTS": false,
            "useSQLCipher": false
          },
          "ios": {
            // You can also override the shared configurations for iOS
            "customBuildFlags": ["-DSQLITE_ENABLE_DBSTAT_VTAB=1 -DSQLITE_ENABLE_SNAPSHOT=1"]
          }
        }
      ]
    ]
  }
}

Configurable properties

NameDefaultDescription
customBuildFlags-

Custom build flags to be passed to the SQLite build process.

enableFTStrue

Whether to enable the FTS3, FTS4 and FTS5 extensions.

useSQLCipherfalse

Use the SQLCipher implementations rather than the default SQLite.

Usage

Import the module from expo-sqlite.

Import the module from expo-sqlite
import * as SQLite from 'expo-sqlite';

Basic CRUD operations

Basic CRUD operations
const db = await SQLite.openDatabaseAsync('databaseName');

// `execAsync()` is useful for bulk queries when you want to execute altogether.
// Please note that `execAsync()` does not escape parameters and may lead to SQL injection.
await db.execAsync(`
PRAGMA journal_mode = WAL;
CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY NOT NULL, value TEXT NOT NULL, intValue INTEGER);
INSERT INTO test (value, intValue) VALUES ('test1', 123);
INSERT INTO test (value, intValue) VALUES ('test2', 456);
INSERT INTO test (value, intValue) VALUES ('test3', 789);
`);

// `runAsync()` is useful when you want to execute some write operations.
const result = await db.runAsync('INSERT INTO test (value, intValue) VALUES (?, ?)', 'aaa', 100);
console.log(result.lastInsertRowId, result.changes);
await db.runAsync('UPDATE test SET intValue = ? WHERE value = ?', 999, 'aaa'); // Binding unnamed parameters from variadic arguments
await db.runAsync('UPDATE test SET intValue = ? WHERE value = ?', [999, 'aaa']); // Binding unnamed parameters from array
await db.runAsync('DELETE FROM test WHERE value = $value', { $value: 'aaa' }); // Binding named parameters from object

// `getFirstAsync()` is useful when you want to get a single row from the database.
const firstRow = await db.getFirstAsync('SELECT * FROM test');
console.log(firstRow.id, firstRow.value, firstRow.intValue);

// `getAllAsync()` is useful when you want to get all results as an array of objects.
const allRows = await db.getAllAsync('SELECT * FROM test');
for (const row of allRows) {
  console.log(row.id, row.value, row.intValue);
}

// `getEachAsync()` is useful when you want to iterate SQLite query cursor.
for await (const row of db.getEachAsync('SELECT * FROM test')) {
  console.log(row.id, row.value, row.intValue);
}

Prepared statements

Prepared statement allows you compile your SQL query once and execute it multiple times with different parameters. You can get a prepared statement by calling prepareAsync() or prepareSync() method on a database instance. The prepared statement can fulfill CRUD operations by calling executeAsync() or executeSync() method.

Note: Remember to call finalizeAsync() or finalizeSync() method to release the prepared statement after you finish using the statement. try-finally block is recommended to ensure the prepared statement is finalized.

Prepared statements
const statement = await db.prepareAsync(
  'INSERT INTO test (value, intValue) VALUES ($value, $intValue)'
);
try {
  let result = await statement.executeAsync({ $value: 'bbb', $intValue: 101 });
  console.log('bbb and 101:', result.lastInsertRowId, result.changes);

  result = await statement.executeAsync({ $value: 'ccc', $intValue: 102 });
  console.log('ccc and 102:', result.lastInsertRowId, result.changes);

  result = await statement.executeAsync({ $value: 'ddd', $intValue: 103 });
  console.log('ddd and 103:', result.lastInsertRowId, result.changes);
} finally {
  await statement.finalizeAsync();
}

const statement2 = await db.prepareAsync('SELECT * FROM test WHERE intValue >= $intValue');
try {
  const result = await statement2.executeAsync<{ value: string; intValue: number }>({
    $intValue: 100,
  });

  // `getFirstAsync()` is useful when you want to get a single row from the database.
  const firstRow = await result.getFirstAsync();
  console.log(firstRow.id, firstRow.value, firstRow.intValue);

  // Reset the SQLite query cursor to the beginning for the next `getAllAsync()` call.
  await result.resetAsync();

  // `getAllAsync()` is useful when you want to get all results as an array of objects.
  const allRows = await result.getAllAsync();
  for (const row of allRows) {
    console.log(row.value, row.intValue);
  }

  // Reset the SQLite query cursor to the beginning for the next `for-await-of` loop.
  await result.resetAsync();

  // The result object is also an async iterable. You can use it in `for-await-of` loop to iterate SQLite query cursor.
  for await (const row of result) {
    console.log(row.value, row.intValue);
  }
} finally {
  await statement2.finalizeAsync();
}

useSQLiteContext() hook

useSQLiteContext() hook
import { SQLiteProvider, useSQLiteContext, type SQLiteDatabase } from 'expo-sqlite';
import { useEffect, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <SQLiteProvider databaseName="test.db" onInit={migrateDbIfNeeded}>
        <Header />
        <Content />
      </SQLiteProvider>
    </View>
  );
}

export function Header() {
  const db = useSQLiteContext();
  const [version, setVersion] = useState('');
  useEffect(() => {
    async function setup() {
      const result = await db.getFirstAsync<{ 'sqlite_version()': string }>(
        'SELECT sqlite_version()'
      );
      setVersion(result['sqlite_version()']);
    }
    setup();
  }, []);
  return (
    <View style={styles.headerContainer}>
      <Text style={styles.headerText}>SQLite version: {version}</Text>
    </View>
  );
}

interface Todo {
  value: string;
  intValue: number;
}

export function Content() {
  const db = useSQLiteContext();
  const [todos, setTodos] = useState<Todo[]>([]);

  useEffect(() => {
    async function setup() {
      const result = await db.getAllAsync<Todo>('SELECT * FROM todos');
      setTodos(result);
    }
    setup();
  }, []);

  return (
    <View style={styles.contentContainer}>
      {todos.map((todo, index) => (
        <View style={styles.todoItemContainer} key={index}>
          <Text>{`${todo.intValue} - ${todo.value}`}</Text>
        </View>
      ))}
    </View>
  );
}

async function migrateDbIfNeeded(db: SQLiteDatabase) {
  const DATABASE_VERSION = 1;
  let { user_version: currentDbVersion } = await db.getFirstAsync<{ user_version: number }>(
    'PRAGMA user_version'
  );
  if (currentDbVersion >= DATABASE_VERSION) {
    return;
  }
  if (currentDbVersion === 0) {
    await db.execAsync(`
PRAGMA journal_mode = 'wal';
CREATE TABLE todos (id INTEGER PRIMARY KEY NOT NULL, value TEXT NOT NULL, intValue INTEGER);
`);
    await db.runAsync('INSERT INTO todos (value, intValue) VALUES (?, ?)', 'hello', 1);
    await db.runAsync('INSERT INTO todos (value, intValue) VALUES (?, ?)', 'world', 2);
    currentDbVersion = 1;
  }
  // if (currentDbVersion === 1) {
  //   Add more migrations
  // }
  await db.execAsync(`PRAGMA user_version = ${DATABASE_VERSION}`);
}

const styles = StyleSheet.create({
  // Your styles...
});

useSQLiteContext() hook with React.Suspense

As with the useSQLiteContext() hook, you can also integrate the SQLiteProvider with React.Suspense to show a fallback component until the database is ready. To enable the integration, pass the useSuspense prop to the SQLiteProvider component.

useSQLiteContext() hook with React.Suspense
import { SQLiteProvider, useSQLiteContext } from 'expo-sqlite';
import { Suspense } from 'react';
import { View, Text, StyleSheet } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Suspense fallback={<Fallback />}>
        <SQLiteProvider databaseName="test.db" onInit={migrateDbIfNeeded} useSuspense>
          <Header />
          <Content />
        </SQLiteProvider>
      </Suspense>
    </View>
  );
}

Executing queries within an async transaction

Executing queries within an async transaction
const db = await SQLite.openDatabaseAsync('databaseName');

await db.withTransactionAsync(async () => {
  const result = await db.getFirstAsync('SELECT COUNT(*) FROM USERS');
  console.log('Count:', result.rows[0]['COUNT(*)']);
});

Due to the nature of async/await, any query that runs while the transaction is active will be included in the transaction. This includes query statements that are outside of the scope function passed to withTransactionAsync() and may be surprising behavior. For example, the following test case runs queries inside and outside of a scope function passed to withTransactionAsync(). However, all of the queries will run within the actual SQL transaction because the second UPDATE query runs before the transaction finishes.

Promise.all([
  // 1. A new transaction begins
  db.withTransactionAsync(async () => {
    // 2. The value "first" is inserted into the test table and we wait 2
    //    seconds
    await db.execAsync('INSERT INTO test (data) VALUES ("first")');
    await sleep(2000);

    // 4. Two seconds in, we read the latest data from the table
    const row = await db.getFirstAsync<{ data: string }>('SELECT data FROM test');

    // ❌ The data in the table will be "second" and this expectation will fail.
    //    Additionally, this expectation will throw an error and roll back the
    //    transaction, including the `UPDATE` query below since it ran within
    //    the transaction.
    expect(row.data).toBe('first');
  }),
  // 3. One second in, the data in the test table is updated to be "second".
  //    This `UPDATE` query runs in the transaction even though its code is
  //    outside of it because the transaction happens to be active at the time
  //    this query runs.
  sleep(1000).then(async () => db.execAsync('UPDATE test SET data = "second"')),
]);

The withExclusiveTransactionAsync() function addresses this. Only queries that run within the scope function passed to withExclusiveTransactionAsync() will run within the actual SQL transaction.

Executing PRAGMA queries

Executing PRAGMA queries
const db = await SQLite.openDatabaseAsync('databaseName');
await db.execAsync('PRAGMA journal_mode = WAL');
await db.execAsync('PRAGMA foreign_keys = ON');
Tip: Enable WAL journal mode when you create a new database to improve performance in general.

Import an existing database

To open a new SQLite database using an existing .db file you already have, you can use the SQLiteProvider with assetSource.

useSQLiteContext() with existing database
import { SQLiteProvider, useSQLiteContext } from 'expo-sqlite';
import { View, Text, StyleSheet } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <SQLiteProvider databaseName="test.db" assetSource={{ assetId: require('./assets/test.db') }}>
        <Header />
        <Content />
      </SQLiteProvider>
    </View>
  );
}

Sharing a database between apps/extensions (iOS)

To share a database with other apps/extensions in the same App Group, you can use shared containers by following the steps below:

1

Configure the App Group in app config:

app.json
{
  "expo": {
    "ios": {
      "bundleIdentifier": "com.myapp",
      "entitlements": {
        "com.apple.security.application-groups": ["group.com.myapp"]
      }
    }
  }
}

2

Use Paths.appleSharedContainers from the expo-file-system library to retrieve the path to the shared container:

Using Shared Container for SQLite Database on iOS
import { SQLiteProvider, defaultDatabaseDirectory } from 'expo-sqlite';
import { Paths } from 'expo-file-system/next';
import { useMemo } from 'react';
import { Platform, View } from 'react-native';

export default function App() {
  const dbDirectory = useMemo(() => {
    if (Platform.OS === 'ios') {
      return Object.values(Paths.appleSharedContainers)?.[0]?.uri;
      // or `Paths.appleSharedContainers['group.com.myapp']?.uri` to choose specific container
    }
    return defaultDatabaseDirectory;
  }, []);

  return (
    <View style={styles.container}>
      <SQLiteProvider databaseName="test.db" directory={dbDirectory}>
        <Header />
        <Content />
      </SQLiteProvider>
    </View>
  );
}

Passing binary data

Use Uint8Array to pass binary data to the database:

Passing binary data
await db.execAsync(`
DROP TABLE IF EXISTS blobs;
CREATE TABLE IF NOT EXISTS blobs (id INTEGER PRIMARY KEY NOT NULL, data BLOB);
`);

const blob = new Uint8Array([0x00, 0x01, 0x02, 0x03, 0x04, 0x05]);
await db.runAsync('INSERT INTO blobs (data) VALUES (?)', blob);

const row = await db.getFirstAsync<{ data: Uint8Array }>('SELECT * FROM blobs');
expect(row.data).toEqual(blob);

Browse an on-device database

You can inspect a database, execute queries against it, and explore data with the drizzle-studio-expo dev tools plugin. This plugin enables you to launch Drizzle Studio, connected to a database in your app, directly from Expo CLI. This plugin can be used with any expo-sqlite configuration. It does not require that you use Drizzle ORM in your app. Learn how to install and use the plugin.

Key-value storage

The expo-sqlite library provides Storage as a drop-in replacement for the @react-native-async-storage/async-storage library. This key-value store is backed by SQLite. If your project already uses expo-sqlite, you can leverage expo-sqlite/kv-store without needing to add another dependency.

Storage provides the same API as @react-native-async-storage/async-storage:

Using the Store
// The storage API is the default export, you can call it Storage, AsyncStorage, or whatever you prefer.
import Storage from 'expo-sqlite/kv-store';

await Storage.setItem('key', JSON.stringify({ entity: 'value' }));
const value = await Storage.getItem('key');
const entity = JSON.parse(value);
console.log(entity); // { entity: 'value' }

A key benefit of using expo-sqlite/kv-store is the addition of synchronous APIs for added convenience:

Using the Store with synchronous APIs
// The storage API is the default export, you can call it Storage, AsyncStorage, or whatever you prefer.
import Storage from 'expo-sqlite/kv-store';

Storage.setItemSync('key', 'value');
const value = Storage.getItemSync('key');

If you're currently using @react-native-async-storage/async-storage in your project, switching to expo-sqlite/kv-store is as simple as changing the import statement:

- import AsyncStorage from '@react-native-async-storage/async-storage';
+ import AsyncStorage from 'expo-sqlite/kv-store';

Third-party library integrations

The expo-sqlite library is designed to be a solid SQLite foundation. It enables broader integrations with third-party libraries for more advanced higher-level features. Here are some of the libraries that you can use with expo-sqlite.

Drizzle ORM

Drizzle is a "headless TypeScript ORM with a head". It runs on Node.js, Bun, Deno, and React Native. It also has a CLI companion called drizzle-kit for generating SQL migrations.

Check out the Drizzle ORM documentation and the expo-sqlite integration guide for more details.

Knex.js

Knex.js is a SQL query builder that is "flexible, portable, and fun to use!"

Check out the expo-sqlite integration guide for more details.

API

Cheatsheet for the common API

The following table summarizes the common API for SQLiteDatabase and SQLiteStatement classes:

SQLiteDatabase methodsSQLiteStatement methodsDescriptionUse Case
runAsync()executeAsync()Executes a SQL query, returning information on the changes made.Ideal for SQL write operations such as INSERT, UPDATE, DELETE.
getFirstAsync()executeAsync() + getFirstAsync()Retrieves the first row from the query result.Suitable for fetching a single row from the database. For example: getFirstAsync('SELECT * FROM Users WHERE id = ?', userId).
getAllAsync()executeAsync() + getFirstAsync()Fetches all query results at once.Best suited for scenarios with smaller result sets, such as queries with a LIMIT clause, like SELECT * FROM Table LIMIT 100, where you intend to retrieve all results in a single batch.
getEachAsync()executeAsync() + for-await-of async iteratorProvides an iterator for result set traversal. This method fetches one row at a time from the database, potentially reducing memory usage compared to getAllAsync().Recommended for handling large result sets incrementally, such as with infinite scrolling implementations.

Component

SQLiteProvider

Android
iOS
macOS

Type: React.Element<SQLiteProviderProps>

Context.Provider component that provides a SQLite database to all children. All descendants of this component will be able to access the database using the useSQLiteContext hook.

SQLiteProviderProps

assetSource

Android
iOS
macOS
Optional • Type: SQLiteProviderAssetSource

Import a bundled database file from the specified asset module.

Example

assetSource={{ assetId: require('./assets/db.db') }}

children

Android
iOS
macOS
Type: ReactNode

The children to render.

databaseName

Android
iOS
macOS
Type: string

The name of the database file to open.

directory

Android
iOS
macOS
Optional • Type: string • Default: defaultDatabaseDirectory

The directory where the database file is located.

onError

Android
iOS
macOS
Optional • Type: (error: Error) => void • Default: rethrow the error

Handle errors from SQLiteProvider.

onInit

Android
iOS
macOS
Optional • Type: (db: SQLiteDatabase) => Promise<void>

A custom initialization handler to run before rendering the children. You can use this to run database migrations or other setup tasks.

options

Android
iOS
macOS
Optional • Type: SQLiteOpenOptions

Open options.

useSuspense

Android
iOS
macOS
Optional • Type: boolean • Default: false

Enable React.Suspense integration.

Example

export default function App() {
  return (
    <Suspense fallback={<Text>Loading...</Text>}>
      <SQLiteProvider databaseName="test.db" useSuspense={true}>
        <Main />
      </SQLiteProvider>
    </Suspense>
  );
}

Constants

SQLite.AsyncStorage

Android
iOS
macOS

Type: SQLiteStorage


This default instance of the SQLiteStorage class is used as a drop-in replacement for the AsyncStorage module from @react-native-async-storage/async-storage.

SQLite.defaultDatabaseDirectory

Android
iOS
macOS

Type: any


The default directory for SQLite databases.

SQLite.Storage

Android
iOS
macOS

Type: SQLiteStorage


Alias for AsyncStorage, given the storage not only offers asynchronous methods.

Hooks

useSQLiteContext()

Android
iOS
macOS

A global hook for accessing the SQLite database across components. This hook should only be used within a <SQLiteProvider> component.

Example

export default function App() {
  return (
    <SQLiteProvider databaseName="test.db">
      <Main />
    </SQLiteProvider>
  );
}

export function Main() {
  const db = useSQLiteContext();
  console.log('sqlite version', db.getFirstSync('SELECT sqlite_version()'));
  return <View />
}

Classes

SQLiteDatabase

Android
iOS
macOS

A SQLite database.

SQLiteDatabase Properties

databasePath

Android
iOS
macOS
Read Only • Type: string

options

Android
iOS
macOS
Read Only • Type: SQLiteOpenOptions

SQLiteDatabase Methods

closeAsync()

Android
iOS
macOS

Close the database.

Returns:

Promise<void>

closeSync()

Android
iOS
macOS

Close the database.

Returns:

void

execAsync(source)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing all the SQL queries.


Execute all SQL queries in the supplied string.

Note: The queries are not escaped for you! Be careful when constructing your queries.

Returns:

Promise<void>

execSync(source)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing all the SQL queries.


Execute all SQL queries in the supplied string.

Note: The queries are not escaped for you! Be careful when constructing your queries.

Note: Running heavy tasks with this function can block the JavaScript thread and affect performance.

Returns:

void

getAllAsync(source, params)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing the SQL query.

paramsSQLiteBindParams

The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See SQLiteBindValue for more information about binding values.


A convenience wrapper around SQLiteDatabase.prepareAsync(), SQLiteStatement.executeAsync(), SQLiteExecuteAsyncResult.getAllAsync(), and SQLiteStatement.finalizeAsync().

Returns:

Promise<T[]>

Example

// For unnamed parameters, you pass values in an array.
db.getAllAsync('SELECT * FROM test WHERE intValue = ? AND name = ?', [1, 'Hello']);

// For unnamed parameters, you pass values in variadic arguments.
db.getAllAsync('SELECT * FROM test WHERE intValue = ? AND name = ?', 1, 'Hello');

// For named parameters, you should pass values in object.
db.getAllAsync('SELECT * FROM test WHERE intValue = $intValue AND name = $name', { $intValue: 1, $name: 'Hello' });

getAllSync(source, params)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing the SQL query.

paramsSQLiteBindParams

The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See SQLiteBindValue for more information about binding values.


A convenience wrapper around SQLiteDatabase.prepareSync(), SQLiteStatement.executeSync(), SQLiteExecuteSyncResult.getAllSync(), and SQLiteStatement.finalizeSync().

Note: Running heavy tasks with this function can block the JavaScript thread and affect performance.

Returns:

T[]

getEachAsync(source, params)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing the SQL query.

paramsSQLiteBindParams

The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See SQLiteBindValue for more information about binding values.


A convenience wrapper around SQLiteDatabase.prepareAsync(), SQLiteStatement.executeAsync(), SQLiteExecuteAsyncResult AsyncIterator, and SQLiteStatement.finalizeAsync().

Returns:

AsyncIterableIterator<T, any, any>

Rather than returning Promise, this function returns an AsyncIterableIterator. You can use for await...of to iterate over the rows from the SQLite query result.

getEachSync(source, params)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing the SQL query.

paramsSQLiteBindParams

The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See SQLiteBindValue for more information about binding values.


A convenience wrapper around SQLiteDatabase.prepareSync(), SQLiteStatement.executeSync(), SQLiteExecuteSyncResult Iterator, and SQLiteStatement.finalizeSync().

Note: Running heavy tasks with this function can block the JavaScript thread and affect performance.

Returns:

IterableIterator<T, any, any>

This function returns an IterableIterator. You can use for...of to iterate over the rows from the SQLite query result.

getFirstAsync(source, params)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing the SQL query.

paramsSQLiteBindParams

The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See SQLiteBindValue for more information about binding values.


A convenience wrapper around SQLiteDatabase.prepareAsync(), SQLiteStatement.executeAsync(), SQLiteExecuteAsyncResult.getFirstAsync(), and SQLiteStatement.finalizeAsync().

Returns:

Promise<null | T>

getFirstSync(source, params)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing the SQL query.

paramsSQLiteBindParams

The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See SQLiteBindValue for more information about binding values.


A convenience wrapper around SQLiteDatabase.prepareSync(), SQLiteStatement.executeSync(), SQLiteExecuteSyncResult.getFirstSync(), and SQLiteStatement.finalizeSync().

Note: Running heavy tasks with this function can block the JavaScript thread and affect performance.

Returns:

null | T

isInTransactionAsync()

Android
iOS
macOS

Asynchronous call to return whether the database is currently in a transaction.

Returns:

Promise<boolean>

isInTransactionSync()

Android
iOS
macOS

Synchronous call to return whether the database is currently in a transaction.

Returns:

boolean

prepareAsync(source)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing the SQL query.


Create a prepared SQLite statement.

prepareSync(source)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing the SQL query.


Create a prepared SQLite statement.

Note: Running heavy tasks with this function can block the JavaScript thread and affect performance.

runAsync(source, params)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing the SQL query.

paramsSQLiteBindParams

The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See SQLiteBindValue for more information about binding values.


A convenience wrapper around SQLiteDatabase.prepareAsync(), SQLiteStatement.executeAsync(), and SQLiteStatement.finalizeAsync().

runSync(source, params)

Android
iOS
macOS
ParameterTypeDescription
sourcestring

A string containing the SQL query.

paramsSQLiteBindParams

The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See SQLiteBindValue for more information about binding values.


A convenience wrapper around SQLiteDatabase.prepareSync(), SQLiteStatement.executeSync(), and SQLiteStatement.finalizeSync().

Note: Running heavy tasks with this function can block the JavaScript thread and affect performance.

serializeAsync(databaseName)

Android
iOS
macOS
ParameterTypeDescription
databaseName
(optional)
string

The name of the current attached databases. The default value is main which is the default database name.

Default:'main'

Serialize the database as Uint8Array.

serializeSync(databaseName)

Android
iOS
macOS
ParameterTypeDescription
databaseName
(optional)
string

The name of the current attached databases. The default value is main which is the default database name.

Default:'main'

Serialize the database as Uint8Array.

Note: Running heavy tasks with this function can block the JavaScript thread and affect performance.

Returns:

Uint8Array

withExclusiveTransactionAsync(task)

Android
iOS
macOS
ParameterTypeDescription
task(txn: Transaction) => Promise<void>

An async function to execute within a transaction. Any queries inside the transaction must be executed on the txn object. The txn object has the same interfaces as the SQLiteDatabase object. You can use txn like a SQLiteDatabase object.


Execute a transaction and automatically commit/rollback based on the task result.

The transaction may be exclusive. As long as the transaction is converted into a write transaction, the other async write queries will abort with database is locked error.

Returns:

Promise<void>

Example

db.withExclusiveTransactionAsync(async (txn) => {
  await txn.execAsync('UPDATE test SET name = "aaa"');
});

withTransactionAsync(task)

Android
iOS
macOS
ParameterTypeDescription
task() => Promise<void>

An async function to execute within a transaction.


Execute a transaction and automatically commit/rollback based on the task result.

Note: This transaction is not exclusive and can be interrupted by other async queries.

Returns:

Promise<void>

Example

db.withTransactionAsync(async () => {
  await db.execAsync('UPDATE test SET name = "aaa"');

  //
  // We cannot control the order of async/await order, so order of execution is not guaranteed.
  // The following UPDATE query out of transaction may be executed here and break the expectation.
  //

  const result = await db.getFirstAsync<{ name: string }>('SELECT name FROM Users');
  expect(result?.name).toBe('aaa');
});
db.execAsync('UPDATE test SET name = "bbb"');

If you worry about the order of execution, use withExclusiveTransactionAsync instead.

withTransactionSync(task)

Android
iOS
macOS
ParameterTypeDescription
task() => void

An async function to execute within a transaction.


Execute a transaction and automatically commit/rollback based on the task result.

Note: Running heavy tasks with this function can block the JavaScript thread and affect performance.

Returns:

void

SQLiteStatement

Android
iOS
macOS

A prepared statement returned by SQLiteDatabase.prepareAsync() or SQLiteDatabase.prepareSync() that can be binded with parameters and executed.

SQLiteStatement Methods

executeAsync(params)

Android
iOS
macOS
ParameterTypeDescription
paramsSQLiteBindParams

The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See SQLiteBindValue for more information about binding values.


Run the prepared statement and return the SQLiteExecuteAsyncResult instance.

executeSync(params)

Android
iOS
macOS
ParameterTypeDescription
paramsSQLiteBindParams

The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See SQLiteBindValue for more information about binding values.


Run the prepared statement and return the SQLiteExecuteSyncResult instance.

Note: Running heavy tasks with this function can block the JavaScript thread and affect performance.

finalizeAsync()

Android
iOS
macOS

Finalize the prepared statement. This will call the sqlite3_finalize() C function under the hood.

Attempting to access a finalized statement will result in an error.

Note: While expo-sqlite will automatically finalize any orphaned prepared statements upon closing the database, it is considered best practice to manually finalize prepared statements as soon as they are no longer needed. This helps to prevent resource leaks. You can use the try...finally statement to ensure that prepared statements are finalized even if an error occurs.

Returns:

Promise<void>

finalizeSync()

Android
iOS
macOS

Finalize the prepared statement. This will call the sqlite3_finalize() C function under the hood.

Attempting to access a finalized statement will result in an error.

Note: While expo-sqlite will automatically finalize any orphaned prepared statements upon closing the database, it is considered best practice to manually finalize prepared statements as soon as they are no longer needed. This helps to prevent resource leaks. You can use the try...finally statement to ensure that prepared statements are finalized even if an error occurs.

Returns:

void

getColumnNamesAsync()

Android
iOS
macOS

Get the column names of the prepared statement.

Returns:

Promise<string[]>

getColumnNamesSync()

Android
iOS
macOS

Get the column names of the prepared statement.

Returns:

string[]

SQLiteStorage

Android
iOS
macOS

Key-value store backed by SQLite. This class accepts a databaseName parameter in its constructor, which is the name of the database file to use for the storage.

SQLiteStorage Methods

clear()

Android
iOS
macOS

Alias for clearAsync() method.

Returns:

Promise<void>

clearAsync()

Android
iOS
macOS

Clears all key-value pairs from the storage asynchronously.

Returns:

Promise<boolean>

clearSync()

Android
iOS
macOS

Clears all key-value pairs from the storage synchronously.

Returns:

boolean

close()

Android
iOS
macOS

Alias for closeAsync() method.

Returns:

Promise<void>

closeAsync()

Android
iOS
macOS

Closes the database connection asynchronously.

Returns:

Promise<void>

closeSync()

Android
iOS
macOS

Closes the database connection synchronously.

Returns:

void

getAllKeys()

Android
iOS
macOS

Alias for getAllKeysAsync() method.

Returns:

Promise<string[]>

getAllKeysAsync()

Android
iOS
macOS

Retrieves all keys stored in the storage asynchronously.

Returns:

Promise<string[]>

getAllKeysSync()

Android
iOS
macOS

Retrieves all keys stored in the storage synchronously.

Returns:

string[]

getItem(key)

Android
iOS
macOS
ParameterType
keystring

Alias for getItemAsync() method.

Returns:

Promise<null | string>

getItemAsync(key)

Android
iOS
macOS
ParameterType
keystring

Retrieves the value associated with the given key asynchronously.

Returns:

Promise<null | string>

getItemSync(key)

Android
iOS
macOS
ParameterType
keystring

Retrieves the value associated with the given key synchronously.

Returns:

null | string

mergeItem(key, value)

Android
iOS
macOS
ParameterType
keystring
valuestring

Merges the given value with the existing value for the given key asynchronously. If the existing value is a JSON object, performs a deep merge.

Returns:

Promise<void>

multiGet(keys)

Android
iOS
macOS
ParameterType
keysstring[]

Retrieves the values associated with the given keys asynchronously.

Returns:

Promise<undefined>

multiMerge(keyValuePairs)

Android
iOS
macOS
ParameterType
keyValuePairsundefined

Merges multiple key-value pairs asynchronously. If existing values are JSON objects, performs a deep merge.

Returns:

Promise<void>

multiRemove(keys)

Android
iOS
macOS
ParameterType
keysstring[]

Removes the values associated with the given keys asynchronously.

Returns:

Promise<void>

multiSet(keyValuePairs)

Android
iOS
macOS
ParameterType
keyValuePairsundefined

Sets multiple key-value pairs asynchronously.

Returns:

Promise<void>

removeItem(key)

Android
iOS
macOS
ParameterType
keystring

Alias for removeItemAsync() method.

Returns:

Promise<void>

removeItemAsync(key)

Android
iOS
macOS
ParameterType
keystring

Removes the value associated with the given key asynchronously.

Returns:

Promise<boolean>

removeItemSync(key)

Android
iOS
macOS
ParameterType
keystring

Removes the value associated with the given key synchronously.

Returns:

boolean

setItem(key, value)

Android
iOS
macOS
ParameterType
key