What is cordova-sqlite-storage? Simple Tutorial with Examples

Alexey Karimov

How do you store and manage structured data inside a Cordova app without relying on an internet connection or unstable local storage options? If your application requires reliable offline access or complex queries, you may want to know about cordova-sqlite-storage.

This plugin provides a native SQLite database layer for Cordova and PhoneGap applications. It provides full SQL support for hybrid apps and operates across Android, iOS, and browser environments. Unlike WebSQL or localStorage, it uses the device’s native SQLite engine, giving developers real database performance with transaction support, persistent storage, and better control over data operations.

Installing cordova-sqlite-storage

Before using SQLite in your Cordova app, you need to install the plugin and ensure the target platforms are added. The process is straightforward and requires only a few commands in your project directory.

Run the following to add the plugin:

cordova plugin add cordova-sqlite-storage

This installs the native SQLite component that works on Android, iOS, and browser platforms. If you have not yet added the platforms, include them as well:

cordova platform add android
cordova platform add ios

After installation, confirm that the plugin is available by running:

cordova plugin list

If you see cordova-sqlite-storage in the list, the setup is successful. The plugin uses native SQLite APIs, not the browser’s WebSQL, which means your data will persist even when the app is closed or offline.

For testing or development builds on desktop browsers, it uses a lightweight JavaScript-based SQLite implementation. Keep in mind that this browser mode is temporary and does not store data permanently, so it should only be used for debugging.

Note: The plugin’s browser fallback depends on your Cordova version and may not be enabled by default. For reliable browser testing, manually include the cordova-sqlite-storage browser proxy or mock SQLite methods.

Creating and Connecting to a Database

Once the plugin is installed, the next step is to create or connect to a database. This should always be done after the Cordova environment is fully loaded, which is when the deviceready event fires. Initializing too early can cause errors because the plugin may not be ready to use.

Here’s how you can safely open a database:

document.addEventListener('deviceready', () => {
    var db = window.sqlitePlugin.openDatabase({
        name: 'appData.db',
        location: 'default'
    });
    console.log('Database opened successfully');
});

This command opens a database named appData.db. If it does not already exist, the plugin automatically creates it. The location parameter defines where the database is stored on the device.

  • Use ‘default‘ for general storage.
  • For iOS, you can also specify ‘Library‘ or ‘Documents‘ if you want finer control over where the database is saved.

If you want to verify that the plugin is working correctly before running queries, you can use simple self-checks provided by the plugin:

window.sqlitePlugin.echoTest(() => {
    console.log('Echo test passed');
});

This test confirms that both the JavaScript and native parts of the plugin are properly linked. Once verified, you are ready to create tables and manage data.

Working with Data (CRUD Operations)

After opening the database, you can start creating tables and performing CRUD operations: Create, Read, Update, and Delete. All queries are executed inside transactions, which ensures data consistency and prevents incomplete operations.

1. Create a Table

Start by creating a simple table to store records.

db.transaction(function (tx) {
    tx.executeSql(
        'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, email TEXT)',
        [],
        () => console.log('Table created successfully'),
        (error) => console.log('Error creating table:', error.message)
    );
});

This code creates a table named users with three fields: id, name, and email. The transaction guarantees that the query is either fully completed or rolled back in the event of an error.

2. Insert Data

Now insert a record into the table.

db.transaction(function (tx) {
    tx.executeSql(
        'INSERT INTO users (name, email) VALUES (?, ?)',
        ['mike', 'mike@example.com'],
        () => console.log('Data inserted successfully'),
        (error) => console.log('Insert failed:', error.message)
    );
});

This code inserts a new record into the users table. The question marks (?, ?) are placeholders that are replaced with the provided array values, which keeps the query safe from SQL injection and syntax issues. The success callback confirms that the record has been added, while the error callback helps identify issues like constraint violations or database locks.

3. Read Data

To read data from the table, use a SELECT query.

db.transaction(function (tx) {
    tx.executeSql(
        'SELECT * FROM users',
        [],
        (tx, result) => {
            for (let i = 0; i < result.rows.length; i++) {
                let row = result.rows.item(i);
                console.log(row.id, row.name, row.email);
            }
        },
        (error) => console.log('Read error:', error.message)
    );
});

This code retrieves all records from the users table. The result.rows object contains the returned rows, and result.rows.item(i) gives access to each one individually. In this example, the loop prints each user’s id, name, and email. This is how data stored in SQLite becomes accessible to your JavaScript code.

4. Update Data

To modify existing records, use an UPDATE query.

db.transaction(function (tx) {
    tx.executeSql(
        'UPDATE users SET name = ? WHERE id = ?',
        ['Arun', 1],
        () => console.log('Record updated successfully'),
        (error) => console.log('Update failed:', error.message)
    );
});

This command updates the record where the id is 1, changing the user’s name to Arun. Transactions ensure that the update happens atomically. Either the change is fully applied or not at all. This prevents partial updates and helps maintain consistent data.

5. Delete Data

Finally, to remove data from the table:

db.transaction(function (tx) {
    tx.executeSql(
        'DELETE FROM users WHERE id = ?',
        [1],
        () => console.log('Record deleted successfully'),
        (error) => console.log('Delete failed:', error.message)
    );
});

This command removes the record with id equal to 1 from the table. The transaction ensures that the delete operation is safely executed. If something goes wrong, such as an invalid ID or locked database, the error callback will provide the failure message for debugging.

If you ever need to clear everything during testing, you can delete the entire database:

window.sqlitePlugin.deleteDatabase({ name: 'appData.db', location: 'default' });

This completely removes the database file from the device, allowing you to start fresh during development or testing.

Wrapping Up

The Cordova SQLite Storage plugin runs reliably on Android, iOS, and browser platforms, while older desktop platforms, such as macOS and Windows, are now deprecated. On the browser, it uses an in-memory SQLite layer through storesafe/sql.js, which is suitable for testing but does not store data permanently.

As a best practice, always perform database operations inside transactions to ensure consistency and prevent partial updates. Keep your SQL queries simple, validate inputs before inserting them, and utilize success and error callbacks to handle unexpected behavior gracefully. 
Testing on actual devices is crucial because performance and permission handling can vary significantly between platforms. When debugging, use self-tests such as echoTest() to confirm that the plugin is correctly linked before deploying your app.