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.
Fundamentals
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.
Foundation
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.
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.
Reference
📝 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.
Cheat Sheet
⚡ Quick Reference
Operation
Code pattern
Open database
openDatabase(name, ver, label, size)
Start transaction
db.transaction(function (tx) { ... })
Insert one row
tx.executeSql('INSERT INTO t (a,b) VALUES (?,?)', [a,b])
Upsert (SQLite)
INSERT OR REPLACE INTO t ...
Skip duplicates
INSERT OR IGNORE INTO t ...
New row id
result.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
Core Topic
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.
Reliability
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 callbacks — db.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');
}
);
Hands-On
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);
}
);
});
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.
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>
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.
Applications
🚀 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.
Important
📝 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.
Compatibility
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 ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
Web SQL APIDeprecated
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.
Pro Tips
💡 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
Wrap Up
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.
Use these points when adding rows to a client-side database.
5
Core concepts
🗃️01
Transaction
Required wrapper.
Basics
➕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.