Web SQL lets you remove rows with a normal SQL DELETE statement, run through tx.executeSql() inside a transaction. Target specific rows with WHERE, or empty a table with DELETE FROM table_name (no WHERE—use carefully).
Pair this with SELECT to list rows first, and INSERT to add fresh data afterward. For new apps, prefer IndexedDB delete.
Deprecated API.
Web SQL is obsolete and removed from modern Chrome. Use this page to maintain legacy code or learn SQL deletes. New projects should use IndexedDB.
Related ideas.
DELETE FROM t empties rows but keeps the table. DROP TABLE removes the table itself. Always bind user values with ?—never concatenate SQL strings.
Syntax
Syntax
syntax.sql
DELETE FROMtable_name WHERE condition
In Web SQL, wrap that statement in executeSql with bound arguments:
JS
tx.executeSql(
'DELETE FROM items WHERE id = ?',
[id],
function (tx, result) { /* success */ },
function (tx, error) { /* failure */ }
);
Reference
Parameters
The executeSql call for a delete takes these arguments:
Argument
Type
Description
sqlStatement
String
The DELETE FROM ... WHERE ... text, with ? placeholders for dynamic values.
arguments
Array
Values bound to each ? in order—e.g. [id].
successCallback
Function (optional)
Called as (tx, result). Inspect result.rowsAffected.
errorCallback
Function (optional)
Called as (tx, error). Return true to roll back the transaction.
Always use WHERE for targeted deletes. Bind values with ?—never paste user input into the SQL string.
Result
Return Value
executeSql does not return a useful value itself. On success, your callback receives (tx, result). For DELETE, use result.rowsAffected to see how many rows were removed.
Property
Type
Meaning after DELETE
result.rowsAffected
Number
How many rows were deleted
result.insertId
Number
Not useful for DELETE (used after INSERT)
result.rows
SQLResultSetRowList
Empty for DELETE (no selected rows)
rowsAffected values:
Value
What it means
0
No row matched your WHERE (wrong id or already deleted). Not an error.
1 or more
That many rows were removed successfully.
Flow
How It Works
A typical single-row delete follows these steps:
Open the database with openDatabase(name, version, displayName, size).
Start a transaction: db.transaction(function (tx) { ... }).
Run DELETE via tx.executeSql(sql, args, success, error).
Check rowsAffected in the success callback.
Handle errors in the error callback (return true to roll back).
JS
db.transaction(function (tx) {
tx.executeSql(
'DELETE FROM contacts WHERE id = ?',
[1],
function (tx, result) {
console.log('Deleted', result.rowsAffected);
},
function (tx, error) {
console.error(error.message);
return true;
}
);
});
Try it
Live Preview
Seed a sample row, then delete it 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…
Code
Examples
Short, copy-ready snippets. Use Try It Yourself for a live editor. Demos need a browser that still exposes openDatabase.
Example 1 — Delete a Row by Id
Remove the item whose primary key is 1.
JS
db.transaction(function (tx) {
tx.executeSql(
'DELETE FROM items WHERE id = ?',
[1],
function (tx, result) {
console.log('Deleted', result.rowsAffected, 'row(s)');
}
);
});
Feature-detectopenDatabase before running any SQL.
Create and seed the table on load.
On button click, run DELETE ... WHERE id = ?.
Update the status text with rowsAffected.
Edge Cases & Pitfalls
Most DELETE bugs come from a missing WHERE, unbound input, or ignoring rowsAffected.
WHERE
No WHERE deletes everything
DELETE FROM items wipes every row. Always double-check the clause before shipping.
inject
Bind with ?
Never build SQL with string concatenation from user input. Pass values in the arguments array.
zero
rowsAffected can be 0
A successful callback with zero rows means nothing matched—show a “not found” message.
tx
Must use a transaction
All executeSql calls belong inside db.transaction() (or readTransaction for reads).
legacy
API may be missing
Feature-detect window.openDatabase. Modern Chrome has no Web SQL—point users to IndexedDB.
Compatibility
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 DELETE
Educational / legacy only. Prefer IndexedDB store.delete() and clear() for new production apps.
LegacyModern browser support
Google ChromeRemoved ~97+
Removed
Mozilla Firefox—
Never supported
Apple SafariLegacy
Historical / limited
Microsoft EdgeRemoved
Removed (Chromium)
OperaRemoved
Removed (Chromium)
Samsung InternetLegacy
Do not rely on
Internet Explorer—
Not supported
Web SQL DELETEDeprecated
Bottom line: For deletes in new web apps, use IndexedDB delete. Keep Web SQL only for maintaining old codebases.
Remember
Key Takeaways
One row:DELETE FROM t WHERE id = ? inside db.transaction().
Receipt: read result.rowsAffected in the success callback.
Safe params: bind values with ?—never concatenate user input.
Legacy: Web SQL is deprecated—use IndexedDB for new projects.
One line: delete with DELETE FROM t WHERE ... via executeSql, check rowsAffected, prefer IndexedDB going forward.
Frequently Asked Questions
Open the database with openDatabase(), then call db.transaction(). Inside the transaction, use tx.executeSql() with DELETE FROM table_name WHERE condition. Bind filter values with ? placeholders: DELETE FROM items WHERE id = ?
Standard SQL: DELETE FROM table_name WHERE condition. Always use WHERE when deleting specific rows—DELETE FROM table_name without WHERE removes every row in the table.
Check result.rowsAffected in the success callback. If it is 0, no row matched your WHERE clause (wrong id or already deleted).
Web SQL requires all executeSql calls within db.transaction(). Transactions keep operations atomic—if a related statement fails, changes can roll back together.
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.
No. Once a transaction commits, deleted rows are gone unless you kept a backup or can re-fetch from a server. Confirm destructive actions in your UI before deleting.