HTML Web SQL INSERT

Beginner
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples + 3 Try It
openDatabase / executeSql

Introduction

Web SQL Database is a browser API that stores structured data in a local SQLite database. You interact with it using familiar SQL statements—including INSERT to add new rows. Although Web SQL is deprecated and no longer recommended for new projects, learning how inserts work helps you maintain legacy apps and understand client-side storage concepts.

This tutorial focuses specifically on inserting data into a Web SQL database: opening the database, creating a table, running INSERT inside transactions, and handling success and errors safely.

What You’ll Learn

01

openDatabase

Open or create DB.

02

CREATE TABLE

Define schema.

03

INSERT

Add new rows.

04

Parameters

Safe ? binding.

05

Callbacks

Success & error.

06

Transactions

Atomic writes.

What Is Web SQL?

Web SQL Database is a deprecated web standard that lets web pages store data in a relational, client-side database. It uses the SQLite engine under the hood, so developers who know SQL from MySQL or PostgreSQL can write similar queries— CREATE TABLE, INSERT, SELECT, UPDATE, and DELETE.

The W3C stopped standardizing Web SQL in 2010 in favor of IndexedDB. Chrome removed Web SQL in version 97 (2022). Safari still supports it in some versions, but you should not build new features on Web SQL. This page teaches the API for learning and legacy maintenance.

💡
Beginner Tip

Think of Web SQL like a tiny database living inside the browser. Every INSERT adds a row to a table—but only after you open the database and wrap the query in a transaction.

Setting Up the Database

Before inserting data, open the database and create the table that will hold your rows.

Step 1 — Open the database

openDatabase(name, version, displayName, estimatedSize) opens an existing database or creates a new one.

js
const db = openDatabase('myDatabase', '1.0', 'Test DB', 2 * 1024 * 1024);
  • name — unique database name (string).
  • version — version string shown to the user.
  • displayName — human-readable label.
  • estimatedSize — expected size in bytes (here, 2 MB).

Step 2 — Create a table

Run CREATE TABLE IF NOT EXISTS inside the first transaction so the schema exists before any inserts.

js
db.transaction(function (tx) {
  tx.executeSql(
    'CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT NOT NULL)'
  );
});

Here id is the primary key and name stores the item label. Adjust columns to match your app’s data model.

📝 INSERT Syntax

Standard SQL INSERT adds one or more rows to a table:

SQL
INSERT INTO table_name (column1, column2) VALUES (value1, value2);

In Web SQL, you call it through executeSql inside a transaction:

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

executeSql Parameters

  • SQL string — the INSERT statement; use ? placeholders for values.
  • Bindings array — values that replace each ? in order (prevents SQL injection).
  • Success callback — runs when the insert succeeds; result.insertId holds the new row id (for AUTOINCREMENT columns).
  • Error callback — runs on failure; read error.message for details.

⚡ Quick Reference

OperationCode pattern
Open databaseopenDatabase(name, ver, label, size)
Start transactiondb.transaction(function (tx) { ... })
Insert one rowtx.executeSql('INSERT INTO t (a,b) VALUES (?,?)', [a,b])
Upsert (SQLite)INSERT OR REPLACE INTO t ...
Skip duplicatesINSERT OR IGNORE INTO t ...
New row idresult.insertId in success callback
Open
openDatabase(...)

Connect

Transaction
db.transaction(tx => ...)

Required wrapper

Bind values
VALUES (?, ?)

Safe params

On error
function(tx, error)

Handle failure

Inserting Data into the Database

Inserting data means running an INSERT statement inside db.transaction. Always use parameterized queries (? placeholders) instead of building SQL strings from user input.

js
function insertItem(id, name) {
  db.transaction(function (tx) {
    tx.executeSql(
      'INSERT INTO items (id, name) VALUES (?, ?)',
      [id, name],
      function (tx, result) {
        console.log('Row inserted. insertId:', result.insertId);
      },
      function (tx, error) {
        console.error('Insert failed:', error.message);
        return true; /* return true to roll back the transaction */
      }
    );
  });
}

Call insertItem(1, 'Sample Item') to add a row. The success callback confirms the write; the error callback lets you log problems or show a message to the user.

Handling Success and Errors

Every executeSql call can succeed or fail. Handle both outcomes explicitly.

  • Success callback — Confirms the INSERT ran. Use result.insertId when the table uses auto-increment ids, or result.rowsAffected to verify one row was added.
  • Error callback — Fires on constraint violations (duplicate primary key), syntax errors, or missing tables. Log error.message and return true to roll back the entire transaction.
  • Transaction-level callbacksdb.transaction(fn, errorFn, successFn) runs errorFn if the transaction fails and successFn when all statements commit.
js
db.transaction(
  function (tx) {
    tx.executeSql('INSERT INTO items (id, name) VALUES (?, ?)', [1, 'Sample Item']);
  },
  function (error) {
    console.error('Transaction rolled back:', error.message);
  },
  function () {
    console.log('Transaction committed successfully');
  }
);

Examples Gallery

These examples use the Web SQL API pattern. Use the Try It Yourself links to run live demos in the editor. Web SQL works only in browsers that still expose openDatabase (legacy Safari/WebKit builds); otherwise the demo shows a clear status message.

📚 Getting Started

Open the database, create a table, and insert your first row.

Example 1 — Insert a Single Row

Minimal insert after creating the items table.

js
const db = openDatabase('myDatabase', '1.0', 'Test DB', 2 * 1024 * 1024);

db.transaction(function (tx) {
  tx.executeSql('CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT)');

  tx.executeSql(
    'INSERT INTO items (id, name) VALUES (?, ?)',
    [1, 'Sample Item'],
    function (tx, result) {
      console.log('Inserted row id:', result.insertId);
    },
    function (tx, error) {
      console.error('Error:', error.message);
    }
  );
});
Try It Yourself

How It Works

The transaction first ensures the table exists, then inserts id 1 with name Sample Item. Bound parameters ([1, 'Sample Item']) keep the query safe from injection.

Example 2 — Reusable insertItem Function

Wrap inserts in a function you can call from buttons or form handlers.

js
function insertItem(id, name) {
  db.transaction(function (tx) {
    tx.executeSql(
      'INSERT INTO items (id, name) VALUES (?, ?)',
      [id, name],
      function () { console.log('Saved:', name); },
      function (tx, error) {
        console.error('Insert error:', error.message);
        return true;
      }
    );
  });
}

insertItem(2, 'Notebook');
insertItem(3, 'Pen');
Try It Yourself

How It Works

Each call starts its own transaction. Returning true from the error callback rolls back that transaction so partial bad data is not committed.

📈 Practical Patterns

Batch inserts, upserts, and a complete HTML demo.

Example 3 — Insert Multiple Rows in One Transaction

Chain several executeSql calls inside a single transaction for atomic batch inserts.

js
const products = [
  { id: 10, name: 'Apple' },
  { id: 11, name: 'Banana' },
  { id: 12, name: 'Cherry' }
];

db.transaction(function (tx) {
  products.forEach(function (p) {
    tx.executeSql(
      'INSERT INTO items (id, name) VALUES (?, ?)',
      [p.id, p.name]
    );
  });
}, function (error) {
  console.error('Batch failed:', error.message);
}, function () {
  console.log('All ' + products.length + ' rows inserted');
});
Try It Yourself

How It Works

If any insert fails, the transaction rolls back and none of the rows are saved. That keeps your table consistent during bulk imports.

Example 4 — INSERT OR REPLACE (Upsert)

SQLite lets you replace an existing row when the primary key already exists.

js
function saveItem(id, name) {
  db.transaction(function (tx) {
    tx.executeSql(
      'INSERT OR REPLACE INTO items (id, name) VALUES (?, ?)',
      [id, name],
      function () { console.log('Upserted id', id); }
    );
  });
}

saveItem(1, 'Original name');
saveItem(1, 'Updated name'); /* replaces the first row */
Try It Yourself

How It Works

The second call does not throw a duplicate-key error—it overwrites the row with id 1. Use this for “save” buttons that should create or update in one step.

Example 5 — Complete HTML Page with Insert Button

A full page that creates the database and inserts data when the user clicks a button.

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Web SQL Insert Example</title>
</head>
<body>
  <h1>Insert Data into Web SQL</h1>
  <button type="button" id="insertBtn">Insert Sample Item</button>
  <p id="status"></p>

  <script>
    if (!window.openDatabase) {
      document.getElementById('status').textContent =
        'Web SQL is not supported in this browser.';
    } else {
      const db = openDatabase('myDatabase', '1.0', 'Test DB', 2 * 1024 * 1024);

      db.transaction(function (tx) {
        tx.executeSql(
          'CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT)'
        );
      });

      function insertItem(id, name) {
        db.transaction(function (tx) {
          tx.executeSql(
            'INSERT INTO items (id, name) VALUES (?, ?)',
            [id, name],
            function () {
              document.getElementById('status').textContent =
                'Inserted: ' + name;
            },
            function (tx, error) {
              document.getElementById('status').textContent =
                'Error: ' + error.message;
              return true;
            }
          );
        });
      }

      document.getElementById('insertBtn').addEventListener('click', function () {
        insertItem(Date.now(), 'Sample Item');
      });
    }
  </script>
</body>
</html>
Try It Yourself

How It Works

The page checks for openDatabase support first. Each button click inserts a row with a unique timestamp id. Status text gives immediate feedback without opening the developer console.

🚀 Common Use Cases

  • Offline form drafts — save user input locally before syncing to a server.
  • Shopping cart cache — persist cart items between page reloads in legacy mobile web apps.
  • Activity logs — append timestamped events to a local audit table.
  • Settings storage — insert default preferences on first visit, then update later.
  • Legacy maintenance — add rows to existing Web SQL databases in older enterprise apps.

🧠 How Web SQL INSERT Works

1

Open database

openDatabase() connects to the local SQLite file.

Connect
2

Begin transaction

db.transaction() wraps one or more SQL statements.

Transaction
3

Run INSERT

tx.executeSql() with bound ? parameters.

Write
=

Row saved

Success callback fires; data persists in the browser until cleared.

📝 Notes

  • Web SQL is deprecated—do not use it for new applications.
  • All executeSql calls must run inside db.transaction.
  • Always bind values with ? placeholders; never concatenate user input into SQL.
  • Validate data in JavaScript before inserting (required fields, types, length limits).
  • Duplicate primary keys cause errors unless you use INSERT OR REPLACE or INSERT OR IGNORE.
  • Storage is per-origin; other sites cannot read your database.

Browser Support

Web SQL was never implemented in Firefox. Chrome shipped it early but removed it in Chrome 97. Safari on iOS/macOS historically supported it. Always feature-detect before calling openDatabase.

Baseline · Since HTML

Web SQL API

Web SQL was never implemented in Firefox. Chrome shipped it early but removed it in Chrome 97. Safari on iOS/macOS historically supported it. Always feature-detect before calling openDatabase.

25% Modern browser support
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
Web SQL API Deprecated

Bottom line: Treat Web SQL as a legacy API. For new client-side storage, use IndexedDB or the simpler localStorage API for small key-value data.

💡 Best Practices

✅ Do

  • Use parameterized queries (? bindings) for every insert
  • Validate and sanitize input before writing to the database
  • Handle both statement-level and transaction-level errors
  • Keep transactions short—batch related inserts together
  • Check window.openDatabase before using the API
  • Choose IndexedDB for all new projects

❌ Don’t

  • Build SQL strings from raw user input
  • Assume inserts succeed without an error callback
  • Store large blobs without size planning
  • Rely on Web SQL for cross-browser apps today
  • Insert duplicate primary keys without an upsert strategy
  • Skip schema setup (CREATE TABLE) before first insert

Conclusion

Inserting data with Web SQL means opening a database, ensuring your table exists, and running INSERT statements inside db.transaction with bound parameters and proper error handling.

While Web SQL is deprecated, understanding inserts helps you read and maintain older codebases. For modern apps, migrate to IndexedDB—but the SQL concepts you learned here (tables, rows, transactions, and safe parameters) transfer directly.

Key Takeaways

Knowledge Unlocked

Five things to remember about Web SQL INSERT

Use these points when adding rows to a client-side database.

5
Core concepts
02

INSERT

Add rows.

SQL
🔒 03

? bindings

Safe params.

Security
⚠️ 04

Error cb

Handle failure.

Reliability
🔄 05

Deprecated

Use IndexedDB.

Modern

❓ Frequently Asked Questions

Open the database with openDatabase(), then call db.transaction(). Inside the transaction, use tx.executeSql() with an INSERT statement. Pass column values as a bound parameter array [id, name] 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.
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, keeping your data consistent.
Pass a fourth argument to executeSql—a function(tx, error) that runs when the statement fails. Log error.message, show user feedback, and avoid assuming the row was saved.
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—useful for upsert-style saves in SQLite/Web SQL.
Did you know?

Web SQL uses the same SQLite engine found in mobile apps and desktop software. That is why you can use SQLite-specific features like INSERT OR REPLACE and INSERT OR IGNORE—but it is also why the API was hard to standardize across browsers, leading to its deprecation.

Practice Web SQL INSERT

Open the Try It editor, click the insert button, and see the status message update on the page.

Open Try It editor →

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.

6 people found this page helpful