Queries and results
Execute SQL with bound values and read rows, counts, metadata, and errors.
SQL statements read or change data in a database. A SELECT returns rows, while statements such as INSERT, UPDATE, and DELETE change rows. Placeholders such as ? let SQLite bind values separately from the SQL text.
Execute a statement
db.execute<Row>(sql, params?) returns a QueryResult<Row> synchronously. db.executeAsync<Row>(sql, params?) returns Promise<QueryResult<Row>> and runs the native work off the JavaScript thread. Use the async method for work that may take long enough to interrupt interaction.
type Note = { id: number; title: string }
await db.executeAsync('INSERT INTO notes (title) VALUES (?)', ['First note'])
const result = await db.executeAsync<Note>(
'SELECT id, title FROM notes WHERE id = ?',
[1],
)
const note = result.rows.item(0)The generic Row describes the row shape you expect; it does not validate SQL or convert values at runtime. Row must be a record of supported SQLite values. Bind application values through params rather than inserting them into SQL text. The supported SQLiteValue union is boolean | number | string | ArrayBuffer | null, and SQLiteQueryParams is an array of those values.
Query result
The connection helpers add rows to the native result:
| Field | Meaning |
|---|---|
results | Array of row objects keyed by column name. |
rows._array | The same result rows in the compatibility row container. |
rows.length | Number of result rows. |
rows.item(index) | Row at the zero-based index, or undefined. |
rowsAffected | SQLite's sqlite3_changes() count. Use it for INSERT, UPDATE, or DELETE; a SELECT can retain the count from an earlier write on the same connection. |
insertId | Optional last insert row ID from the connection. It can refer to an earlier insert. |
metadata | Optional map of column metadata keyed by result column name. |
Each metadata entry has name, index, and type. The ColumnType type declares numeric values BOOLEAN = 0, NUMBER = 1, INT64 = 2, TEXT = 3, ARRAY_BUFFER = 4, and NULL_VALUE = 5. The package root exports this as a type, not as a runtime enum value. The current native mapper can report the wrong metadata.type, so do not use it to determine a column's declared SQLite type.
For a SELECT, use rows.length or results.length to count the rows returned. rowsAffected is not a result-row count.
const result = db.execute('SELECT id, title FROM notes LIMIT 1')
for (const [column, info] of Object.entries(result.metadata ?? {})) {
console.log(column, info.type, info.index)
}Errors
The connection helpers wrap database failures in NitroSQLiteError. This includes failed queries and queue errors such as trying to run a synchronous operation while an async operation owns the connection. Its type field identifies a recognized native exception category, such as SqlExecutionError, and is undefined for queue errors. It is not a numeric SQLite error code. See types and errors.
import { NitroSQLiteError } from 'react-native-nitro-sqlite'
try {
await db.executeAsync('SELECT * FROM missing_table')
} catch (error) {
if (error instanceof NitroSQLiteError) {
console.error(error.message)
} else {
throw error
}
}See Transactions and batches when several statements must succeed together.