HTML Web SQL INSERT

Beginner
8 min read
Updated: Nov 2026
5 examples
Live preview

Definition and Usage

Web SQL lets you add rows with a normal SQL INSERT statement, run through tx.executeSql() inside a transaction. Bind values with ?, then read result.insertId for the new row’s id when you use an auto-increment primary key.

Pair this with SELECT to read rows back, and UPDATE to change them later. For new apps, prefer IndexedDB insert.

Deprecated API.

Web SQL is obsolete and removed from modern Chrome. Use this page to maintain legacy code or learn SQL inserts. New projects should use IndexedDB.

Related ideas.

INSERT OR REPLACE upserts by primary key. INSERT OR IGNORE skips duplicates. Always bind user values with ?—never concatenate SQL strings.

Syntax

syntax.sql
INSERT INTO table_name (columns) VALUES (?, …)

In Web SQL, wrap that statement in executeSql with bound arguments:

JS
tx.executeSql(
  'INSERT INTO items (name, qty) VALUES (?, ?)',
  [name, qty],
  function (tx, result) { /* success */ },
  function (tx, error)  { /* failure */ }
);

Parameters

The executeSql call for an insert takes these arguments:

ArgumentTypeDescription
sqlStatementStringThe INSERT INTO ... VALUES (...) text, with ? placeholders for dynamic values.
argumentsArrayValues bound to each ? in order—e.g. ['Notebook', 2].
successCallbackFunction (optional)Called as (tx, result). Inspect result.insertId and result.rowsAffected.
errorCallbackFunction (optional)Called as (tx, error). Return true to roll back the transaction.

List column names explicitly. Bind values with ?—never paste user input into the SQL string.

Return Value

executeSql does not return a useful value itself. On success, your callback receives (tx, result). For INSERT, use result.insertId for the new row id and result.rowsAffected to confirm a row was added.

PropertyTypeMeaning after INSERT
result.insertIdNumberThe new row’s id (SQLite rowid / INTEGER PRIMARY KEY)
result.rowsAffectedNumberHow many rows were inserted (usually 1)
result.rowsSQLResultSetRowListEmpty for INSERT (no selected rows)

rowsAffected values:

ValueWhat it means
0No row was inserted (common with INSERT OR IGNORE when a duplicate key exists).
1 or moreThat many rows were added (or replaced with INSERT OR REPLACE).

How It Works

A typical single-row insert follows these steps:

  1. Open the database with openDatabase(name, version, displayName, size).
  2. Start a transaction: db.transaction(function (tx) { ... }).
  3. Ensure the table exists with CREATE TABLE IF NOT EXISTS if needed.
  4. Run INSERT via tx.executeSql(sql, args, success, error).
  5. Read insertId / rowsAffected in the success callback.
JS
db.transaction(function (tx) {
  tx.executeSql(
    'INSERT INTO contacts (name, email) VALUES (?, ?)',
    ['Alex Rivera', '[email protected]'],
    function (tx, result) {
      console.log('Inserted id', result.insertId);
    },
    function (tx, error) {
      console.error(error.message);
      return true;
    }
  );
});

Live Preview

Insert a contact, list rows, or clear the table. Status updates below. Many modern browsers no longer support Web SQL—if so, the status box will say so.

Uses a private demo database when Web SQL is available. Prefer IndexedDB for new work.

Status

Checking Web SQL support…

Examples

Short, copy-ready snippets. Use Try It Yourself for a live editor. Demos need a browser that still exposes openDatabase.

Example 1 — Basic INSERT

Add one row with bound ? parameters.

JS
db.transaction(function (tx) {
  tx.executeSql(
    'INSERT INTO items (name, qty) VALUES (?, ?)',
    ['Notebook', 2],
    function (tx, result) {
      console.log('Inserted', result.rowsAffected, 'row(s)');
    }
  );
});
Try It Yourself

How It Works

  1. Open a transaction on the database.
  2. Run INSERT ... VALUES (?, ?) with a bound args array.
  3. Log rowsAffected to confirm the insert.

Example 2 — Read insertId

Capture the auto-generated primary key after insert.

JS
db.transaction(function (tx) {
  tx.executeSql(
    'INSERT INTO contacts (name, email) VALUES (?, ?)',
    ['Sam Lee', '[email protected]'],
    function (tx, result) {
      console.log('New contact id:', result.insertId);
    }
  );
});
Try It Yourself

How It Works

  1. Omit the id column so SQLite assigns one.
  2. Read result.insertId in the success callback.
  3. Use that id later for UPDATE, DELETE, or UI keys.

Example 3 — INSERT OR REPLACE

Upsert by primary key: replace the existing row if the key already exists.

JS
db.transaction(function (tx) {
  tx.executeSql(
    'INSERT OR REPLACE INTO items (id, name, qty) VALUES (?, ?, ?)',
    [1, 'Notebook', 5],
    function (tx, result) {
      console.log('Upserted; rowsAffected =', result.rowsAffected);
    }
  );
});
Try It Yourself

How It Works

  1. Include the primary key in the column list.
  2. Use INSERT OR REPLACE instead of plain INSERT.
  3. Existing row with that key is replaced in one statement.

Example 4 — INSERT OR IGNORE

Skip the insert when a unique constraint would fail—keep the original row.

JS
db.transaction(function (tx) {
  tx.executeSql(
    'INSERT OR IGNORE INTO items (id, name) VALUES (?, ?)',
    [1, 'Duplicate attempt'],
    function (tx, result) {
      if (result.rowsAffected === 0) {
        console.log('Ignored — id 1 already exists');
      } else {
        console.log('Inserted id', result.insertId);
      }
    }
  );
});
Try It Yourself

How It Works

  1. Use INSERT OR IGNORE for soft duplicate handling.
  2. Check rowsAffected—0 means the row was skipped.
  3. No error callback fires for a ignored duplicate.

Example 5 — Complete HTML Page

Create a table on load, then insert a row from a button click.

HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Web SQL Insert Demo</title>
</head>
<body>
  <h1>Web SQL INSERT</h1>
  <button type="button" id="insertBtn">Insert sample</button>
  <p id="status">Opening…</p>

  <script>
    var statusEl = document.getElementById('status');
    if (!window.openDatabase) {
      statusEl.textContent = 'Web SQL is not available in this browser.';
    } else {
      var db = openDatabase('insertDemoDb', '1.0', 'Demo', 1024 * 1024);
      db.transaction(function (tx) {
        tx.executeSql(
          'CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT, qty INTEGER)'
        );
      }, null, function () {
        statusEl.textContent = 'Ready. Click Insert.';
      });

      document.getElementById('insertBtn').addEventListener('click', function () {
        db.transaction(function (tx) {
          tx.executeSql(
            'INSERT INTO items (name, qty) VALUES (?, ?)',
            ['Sample', 1],
            function (tx, result) {
              statusEl.textContent = 'Inserted id ' + result.insertId + '.';
            }
          );
        });
      });
    }
  </script>
</body>
</html>
Try It Yourself

How It Works

  1. Feature-detect openDatabase before running any SQL.
  2. Create the table on load with IF NOT EXISTS.
  3. On button click, run INSERT ... VALUES (?, ?).
  4. Show insertId in the status text.

Edge Cases & Pitfalls

Most INSERT bugs come from unbound input, missing tables, or ignoring constraint conflicts.

inject

Bind with ?

Never build SQL with string concatenation from user input. Pass values in the arguments array.

unique

Duplicate keys fail

Plain INSERT errors on unique conflicts. Use OR REPLACE or OR IGNORE when that is intentional.

schema

Create the table first

Run CREATE TABLE IF NOT EXISTS before inserting, or the statement fails with “no such table”.

tx

Must use a transaction

All executeSql calls belong inside db.transaction().

legacy

API may be missing

Feature-detect window.openDatabase. Modern Chrome has no Web SQL—point users to IndexedDB.

Browser Support

Web SQL is a deprecated client-side API. Firefox never shipped it. Chrome removed it (about Chrome 97+). Detect with window.openDatabase before running demos.

✓ Deprecated

Web SQL INSERT

Educational / legacy only. Prefer IndexedDB add() and put() for new production apps.

Legacy Modern browser support
Google Chrome Removed ~97+
Removed
Mozilla Firefox —
Never supported
Apple Safari Legacy
Historical / limited
Microsoft Edge Removed
Removed (Chromium)
Opera Removed
Removed (Chromium)
Samsung Internet Legacy
Do not rely on
Internet Explorer —
Not supported
Web SQL INSERT Deprecated

Bottom line: For inserts in new web apps, use IndexedDB insert. Keep Web SQL only for maintaining old codebases.

Key Takeaways

  • Add a row: INSERT INTO t (cols) VALUES (?, ?) inside db.transaction().
  • New id: read result.insertId in the success callback.
  • Conflicts: use OR REPLACE or OR IGNORE instead of plain INSERT.
  • Legacy: Web SQL is deprecated—use IndexedDB for new projects.

One line: insert with INSERT INTO t (...) VALUES (?, ?) via executeSql, read insertId, prefer IndexedDB going forward.

Frequently Asked Questions

Open the database with openDatabase(), then call db.transaction(). Inside the transaction, use tx.executeSql() with INSERT INTO table (col1, col2) VALUES (?, ?). Pass column values as a bound parameter array instead of concatenating strings into the SQL.
Standard SQL: INSERT INTO table_name (col1, col2) VALUES (?, ?). Web SQL uses SQLite under the hood, so INSERT OR REPLACE and INSERT OR IGNORE are also supported for upserts and duplicate handling.
Read result.insertId in the success callback of executeSql. It holds the rowid SQLite assigned, which matches an INTEGER PRIMARY KEY column when your table uses one.
Web SQL requires all executeSql calls to run within db.transaction(). Transactions group operations atomically—if one statement fails, the whole transaction can roll back.
Web SQL is deprecated and removed from most modern browsers (including current Chrome). Treat this tutorial as educational for legacy code; use IndexedDB for new projects.
Plain INSERT fails if a unique constraint is violated. INSERT OR REPLACE deletes the existing row with the same key and inserts the new one. INSERT OR IGNORE silently skips the new row and keeps the original.

Next: Web SQL Retrieve

Read rows with SELECT after you insert them.

Retrieve tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

10 people found this page helpful