.prepare(string) -> Statement

.transaction(function) -> function

Creates a function that always runs inside a transaction. When the function is invoked, it will begin a new transaction. When the function returns, the transaction will be committed. If an exception is thrown, the transaction will be rolled back (and the exception will propagate as usual).

Caveats

If you'd like to manage transactions manually, you're free to do so with regular prepared statements (using BEGIN, COMMIT, etc.). However, manually managed transactions should not be mixed with transactions managed by this .transaction() method. In other words, using raw COMMIT or ROLLBACK statements inside a transaction function is not supported.

Transaction functions do not work with async functions. Technically speaking, async functions always return after the first await, which means the transaction will already be committed before any async code executes. Also, because SQLite3 serializes all transactions, it's generally a very bad idea to keep a transaction open across event loop ticks anyways.

It's important to know that SQLite3 may sometimes rollback a transaction without us asking it to. This can happen either because of an ON CONFLICT clause, the RAISE() trigger function, or certain errors such as SQLITE_FULL or SQLITE_BUSY. When this occurs, transaction functions will automatically detect the situation and handle it appropriately. However, if you catch one of these errors with a try-catch statement, you become responsible for handling the case. In other words, all catch statements within transaction functions should look like this:

It's better to use this method instead of normal prepared statements when executing PRAGMA, because this method normalizes some odd behavior that may otherwise be experienced. The documentation on SQLite3 PRAGMA can be found here.

.checkpoint([databaseName]) -> this

Unlike automatic checkpoints, this method executes a checkpoint in "RESTART" mode, which ensures a complete checkpoint operation even if other processes are using the database at the same time. You only need to use this method if you are accessing the database from multiple processes at the same time.

setInterval(() =>db.checkpoint(), 30000).unref();

If databaseName is provided, it should be the name of an attached database (or "main"). This causes only that database to be checkpointed.

If the checkpoint fails, an Error is thrown.

.backup(destination, [options]) -> promise

Initiates a backup of the database, returning a promise for when the backup is complete. If the backup fails, the promise will be rejected with an Error. You can optionally backup an attached database by setting the attached option to the name of the desired attached database.

You can continue to use the database normally while a backup is in progress. If the same database connection mutates the database while performing a backup, those mutations will be reflected in the backup automatically. However, if a different connection mutates the database during a backup, the backup will be forcefully restarted. Therefore, it's recommended that only a single connection is responsible for mutating the database if online backups are being performed.

You can monitor the progress of the backup by setting the progress option to a callback function. That function will be invoked every time the backup makes progress, providing an object with two properties:

.totalPages: the total number of pages in the source database (and thus, the number of pages that the backup will have when completed) at the time of this progress report.

.remainingPages: the number of pages that still must be transferred before the backup is complete.

By default, 100pages will be transferred after each cycle of the event loop. However, you can change this setting as often as you like by returning a number from the progress callback. You can even return 0 to effectively pause the backup altogether. In general, the goal is to maximize throughput while reducing pause times. If the transfer size is very low, pause times will be low, but it may take a while to complete the backup. On the flip side, if the setting is too high, pause times will be greater, but the backup might complete sooner. In most cases, 100 has proven to be a strong compromise, but the best setting is dependent on your computer's specifications and the nature of your program. Do not change this setting without measuring the effectiveness of your change. You should not assume that your change will even have the intended effect, unless you measure it for your unique situation.

If the progress callback throws an exception, the backup will be aborted. Usually this happens due to an unexpected error, but you can also use this behavior to voluntarily cancel the backup operation. If the parent database connection is closed, all pending backups will be automatically aborted.

By default, user-defined functions have a strict number of arguments (determined by function.length). You can register multiple functions of the same name, each with a different number of arguments, causing SQLite3 to execute a different function depending on how many arguments were passed to it. If you register two functions with same name and the same number of arguments, the second registration will erase the first one.

If options.varargs is true, the registered function can accept any number of arguments.

If your function is deterministic, you can set options.deterministic to true, which may improve performance under some circumstances.

The step() function will be invoked once for each row passed to the aggregate, using its return value as the new aggregate value. This works similarly to Array#reduce().

If options.start is a function, it will be invoked at the beginning of each aggregate, using its return value as the initial aggregate value. If options.start is not a function, it will be used as the initial aggregate value as-is (shown in the example above). If not provided, the initial aggregate value will be null.

You can also provide a result() function to transform the final aggregate value:

As shown above, you can use arbitrary JavaScript objects as your aggregation context, as long as a valid SQLite3 value is returned by result() in the end. If step() doesn't return anything (undefined), the aggregate value will not be replaced (be careful of this when using functions that return undefined when null is desired).

If you provide an inverse() function, the aggregate can be used as a window function. Where step() is used to add a row to the current window, inverse() is used to remove a row from the current window. When using window functions, result() may be invoked multiple times.

.loadExtension(path) -> this

Loads a compiled SQLite3 extension and applies it to the current database connection.

It's your responsibility to make sure the extensions you load are compiled/linked against a version of SQLite3 that is compatible with better-sqlite3. Keep in mind that new versions of better-sqlite3 will periodically use newer versions of SQLite3. You can see which version is being used here.

db.loadExtension('./my-extensions/compress.so');

.exec(string) -> this

Executes the given SQL string. Unlike prepared statements, this can execute strings that contain multiple SQL statements. This function performs worse and is less safe than using prepared statements. You should only use this method when you need to execute SQL from an external source (usually a file). If an error occurs, execution stops and further statements are not executed. You must rollback changes manually.

info.lastInsertRowid: the rowid of the last row inserted into the database (ignoring those caused by trigger programs). If the current statement did not insert any rows into the database, this number should be completely ignored.

If execution of the statement fails, an Error is thrown.

You can specify bind parameters, which are only bound for the given execution.

.iterate([...bindParameters]) -> iterator

*(only on statements that return data)

Similar to .all(), but instead of returning every row together, an iterator is returned so you can retrieve the rows one by one. If you plan on retrieving every row anyways, .all() will perform slightly better.

If execution of the statement fails, an Error is thrown and the iterator is closed.

You can specify bind parameters, which are only bound for the given execution.

When plucking is turned on, expansion and raw mode are turned off (they are mutually exclusive options).

.expand([toggleState]) -> this

*(only on statements that return data)

Causes the prepared statement to return data namespaced by table. Each key in a row object will be a table name, and each corresponding value will be a nested object that contains the associated column data. This is useful when performing a JOIN between two tables that have overlapping column names. If a result column is an expression or subquery, it will be available within the special $ namespace.

When expansion is turned on, plucking and raw mode are turned off (they are mutually exclusive options).

.raw([toggleState]) -> this

*(only on statements that return data)

Causes the prepared statement to return rows as arrays instead of objects. This is primarily used as a performance optimization when retrieving a very high number of rows. Column names can be recovered by using the .columns() method.

When raw mode is turned on, plucking and expansion are turned off (they are mutually exclusive options).

.columns() -> array of objects

*(only on statements that return data)

This method is primarily used in conjunction with raw mode. It returns an array of objects, where each object describes a result column of the prepared statement. Each object has the following properties:

.name: the name (or alias) of the result column.

.column: the name of the originating table column, or null if it's an expression or subquery.

.table: the name of the originating table, or null if it's an expression or subquery.

.database: the name of the originating database, or null if it's an
expression or subquery.

.type: the name of the declared type, or null if it's an expression or subquery.

When a table's schema is altered, existing prepared statements might start returning different result columns. However, such changes will not be reflected by this method until the prepared statement is re-executed. For this reason, it's perhaps better to invoke .columns()after.get(), .all(), or .iterate().

.bind([...bindParameters]) -> this

Binds the given parameters to the statement permanently. Unlike binding parameters upon execution, these parameters will stay bound to the prepared statement for its entire life.

After a statement's parameters are bound this way, you may no longer provide it with execution-specific (temporary) bound parameters.

This method is primarily used as a performance optimization when you need to execute the same prepared statement many times with the same bound parameters.