HTML Web SQL UPDATE

Beginner
⏱️ ~10–12 min
📚 Updated: Aug 2026
🎯 5 Examples
🚀 5 Try-it labs
UPDATE · SET · WHERE · rowsAffected

What You’ll Learn

Web SQL Database is a deprecated browser API that stores structured data in a local SQLite database. The SQL UPDATE statement changes existing rows—user profiles, settings, cart quantities, or sync flags—without deleting and re-inserting them. This tutorial covers UPDATE syntax, targeting rows with WHERE, listing columns with SET, binding safe ? parameters, checking rowsAffected, handling errors, five worked examples, and why Web SQL is deprecated in favor of IndexedDB.

UPDATE

Core statement

Change column values on rows that already exist with a standard SQL UPDATE statement.

SET

New values

List one or more column = value pairs to change—untouched columns keep their data.

WHERE

Target rows

Filter exactly which rows change—omit it and the whole table is updated.

? bindings

Safe params

Bind new values and ids with ? placeholders instead of concatenating SQL.

rowsAffected

Verify change

Confirm how many rows actually changed—zero means no match, not necessarily an error.

Transactions

Atomic writes

Every executeSql call runs inside db.transaction().

Introduction

Web SQL Database is a deprecated browser API for client-side relational storage. It uses SQLite under the hood, so standard SQL statements—including UPDATE—work just like they do on server-side databases.

The W3C deprecated Web SQL in favor of IndexedDB, and Chrome removed it in version 97. Although the API is no longer recommended for new projects, understanding UPDATE still helps you maintain legacy applications and grasp the SQL fundamentals that carry over to other databases.

Why it matters?

Data rarely stays static—users edit profiles, toggle settings, or an app marks a row as synced. UPDATE is the only way to change data in place in a SQL database; done carelessly (missing a WHERE, ignoring rowsAffected) it is also an easy way to overwrite data you meant to keep untouched.

Key Highlights

Changes Rows In Place

Modifies existing columns without deleting or re-inserting the row.

WHERE Required

Always target rows with WHERE—without it, every row is updated.

Bound Parameters

? placeholders keep new values and ids safe from SQL injection.

Deprecated API

Web SQL is educational for legacy code—use IndexedDB for new work.

In short: UPDATE table SET col = ? WHERE condition, bound with ?, inside a transaction, confirmed with rowsAffected—that pattern changes rows safely in Web SQL and in most SQL databases.

Creating the Database and Seeding a Row

Before updating, open the database and make sure the table exists. Seed a starter row with INSERT OR IGNORE so there is something to update in every example below.

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

db.transaction(function (tx) {
  tx.executeSql(
    'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)'
  );
  tx.executeSql(
    'INSERT OR IGNORE INTO users (id, name, age) VALUES (?, ?, ?)',
    [1, 'John Doe', 25]
  );
});

INSERT OR IGNORE adds the starter row only if id 1 does not exist yet—handy for demos and first-run setup, and it means re-running this snippet never throws a duplicate-key error.

📝 UPDATE Syntax

Standard SQL syntax for modifying existing rows:

SQL
UPDATE table_name
SET column1 = value1, column2 = value2
WHERE condition;

In Web SQL, call it through executeSql with bound parameters:

js
tx.executeSql(
  'UPDATE users SET name = ?, age = ? WHERE id = ?',
  [newName, newAge, id],
  function (tx, result) { /* success */ },
  function (tx, error)  { /* failure */ }
);

executeSql arguments

ArgumentDescription
sqlStatementThe UPDATE ... SET ... WHERE ... string, with ? placeholders for dynamic values.
argumentsArray of values bound to each ?, in order—e.g. [newName, newAge, id].
successCallback (optional)Called as (tx, result); inspect result.rowsAffected.
errorCallback (optional)Called as (tx, error); return true to roll back the transaction.

Important rules

  • Always use WHERE when updating specific rows—omitting it updates every row in the table.
  • List only the columns you mean to change in SET—untouched columns keep their existing values.
  • Bind values with ? — never concatenate user input into the SQL string.
  • Check result.rowsAffected — zero means no row matched (wrong id or missing record).

⚡ Quick Reference

OperationCode pattern
Update one rowUPDATE t SET col = ? WHERE id = ?
Update multiple columnsSET name = ?, age = ? WHERE id = ?
Verify successresult.rowsAffected > 0
No matchrowsAffected === 0 — row not found
Update all rowsUPDATE t SET status = ? (no WHERE — use carefully)
Target
WHERE id = ?

One row

Set values
SET name = ?, age = ?

New data

Check
rowsAffected

Confirm hit

Wrapper
db.transaction()

Required

📋 UPDATE vs INSERT OR REPLACE vs DELETE

All three change what a table holds—but they disagree on what happens to the row itself.

UPDATE
edits rows

Changes only the columns you list in SET—other columns and the row itself stay intact.

OR REPLACE
overwrites row

Deletes the whole existing row with the same key, then inserts a brand-new one—every column must be supplied again.

DELETE
removes rows

Drops matching rows entirely—use it when data should disappear, not change.

See the full INSERT tutorial for creating new rows and DELETE tutorial for removing them instead of editing in place.

Context

When to Update Rows

Reach for UPDATE whenever a row already exists and only some of its data needs to change.

  1. Edit a profile

    The user changes their display name, bio, or avatar—update that one row by id.

  2. Persist a setting

    Toggle theme, language, or notification flags and save the new value with UPDATE.

  3. Flag sync status

    Mark a row as “sent to server” after a background upload succeeds.

  4. Adjust a quantity

    Increase or decrease a cart item’s qty column when the user changes it.

  5. Not on a row that may not exist

    UPDATE silently changes zero rows if the id is missing—use INSERT first, or INSERT OR REPLACE for an upsert.

Key benefit: a precise SET list plus a targeted WHERE clause changes exactly the fields you intend—nothing more, nothing less.

Executing Update Queries

The UPDATE statement modifies columns on rows that match your WHERE condition. Wrap the logic in a reusable function:

js
function updateRecord(id, newName, newAge) {
  db.transaction(function (tx) {
    tx.executeSql(
      'UPDATE users SET name = ?, age = ? WHERE id = ?',
      [newName, newAge, id],
      function (tx, result) {
        console.log('Rows updated:', result.rowsAffected);
      },
      function (tx, error) {
        console.error('Update error:', error.message);
        return true;
      }
    );
  });
}

updateRecord(1, 'Jane Doe', 26);
  • openDatabase — opens or creates the Web SQL database.
  • transaction — wraps the update in an atomic unit.
  • executeSql — runs UPDATE ... SET ... WHERE id = ? with bound parameters.

This updates the name and age columns for the user with id = 1—every other column on that row is left untouched.

Handling Update Errors

Updates can “succeed” with rowsAffected === 0 when no row matches—that is not a SQL error, just a miss. Always inspect rowsAffected in the success callback and handle real SQL errors in the error callback.

js
tx.executeSql(
  'UPDATE users SET name = ?, age = ? WHERE id = ?',
  [newName, newAge, id],
  function (tx, result) {
    if (result.rowsAffected === 0) {
      console.warn('No records were updated — check the id.');
    } else {
      console.log('Record updated successfully.');
    }
  },
  function (tx, error) {
    console.error('Update error:', error.message);
    return true;
  }
);
  • rowsAffected === 0 — the query ran but matched no rows (wrong id, or row was never inserted).
  • Error callback — syntax errors, constraint violations, or missing tables.
  • Return true from the error callback to roll back the transaction.

Examples Gallery

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

📚 Getting Started

Update a single row by id with bound parameters, then wrap the pattern in a reusable function.

Example 1 — Update a Single Row

Change name and age for user id 1.

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

db.transaction(function (tx) {
  tx.executeSql('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)');
  tx.executeSql('INSERT OR IGNORE INTO users (id, name, age) VALUES (?, ?, ?)', [1, 'John Doe', 25]);

  tx.executeSql(
    'UPDATE users SET name = ?, age = ? WHERE id = ?',
    ['Jane Doe', 26, 1],
    function (tx, result) {
      console.log('Updated rows:', result.rowsAffected);
    },
    function (tx, error) {
      console.error('Error:', error.message);
    }
  );
});
Try It Yourself

How It Works

The transaction creates the table, seeds John Doe, then updates that row to Jane Doe age 26. rowsAffected returns 1 when exactly one row changed.

Example 2 — Reusable updateRecord Function

Call the same function from buttons, forms, or sync handlers.

js
function updateRecord(id, newName, newAge) {
  db.transaction(function (tx) {
    tx.executeSql(
      'UPDATE users SET name = ?, age = ? WHERE id = ?',
      [newName, newAge, id],
      function (tx, result) {
        console.log('Updated', result.rowsAffected, 'row(s) for id', id);
      },
      function (tx, error) {
        console.error('Update error:', error.message);
        return true;
      }
    );
  });
}

updateRecord(1, 'Jane Doe', 26);
updateRecord(2, 'Alex Kim', 30); /* id 2 does not exist */
Try It Yourself

How It Works

The second call returns 0 rows if id 2 was never inserted—a signal to insert first or show “user not found” rather than assuming success.

📈 Practical Patterns

Detect missing rows, bind form values, and build a complete demo page.

Example 3 — Detect When No Row Matches

Use rowsAffected to warn when the target id does not exist.

js
function updateUser(id, name) {
  db.transaction(function (tx) {
    tx.executeSql(
      'UPDATE users SET name = ? WHERE id = ?',
      [name, id],
      function (tx, result) {
        if (result.rowsAffected === 0) {
          console.warn('No user with id', id);
        } else {
          console.log('Name updated for id', id);
        }
      }
    );
  });
}

updateUser(99, 'Ghost User'); /* id 99 does not exist */
Try It Yourself

How It Works

Unlike a SQL error, updating a missing id succeeds with rowsAffected === 0. Your app should treat that as “not found” rather than success.

Example 4 — Update from Form Input

Read values from input fields and bind them to the UPDATE query.

js
document.getElementById('saveBtn').addEventListener('click', function () {
  const name = document.getElementById('nameInput').value.trim();
  const age  = parseInt(document.getElementById('ageInput').value, 10);

  if (!name || isNaN(age)) return;

  db.transaction(function (tx) {
    tx.executeSql(
      'UPDATE users SET name = ?, age = ? WHERE id = ?',
      [name, age, 1],
      function (tx, result) {
        alert(result.rowsAffected ? 'Saved!' : 'User not found.');
      }
    );
  });
});
Try It Yourself

How It Works

Validate input in JavaScript first, then pass clean values through ? bindings. Never build SQL like "UPDATE ... SET name = '" + name + "'".

Example 5 — Complete HTML Page (Add + Update)

Insert a record, then update it with a second button—matching the classic Web SQL workflow.

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Web SQL Update Example</title>
</head>
<body>
  <h1>Web SQL Update Example</h1>
  <button type="button" id="addRecord">Add Record</button>
  <button type="button" id="updateRecord">Update Record</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 users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)'
        );
      });

      document.getElementById('addRecord').addEventListener('click', function () {
        db.transaction(function (tx) {
          tx.executeSql(
            'INSERT OR REPLACE INTO users (id, name, age) VALUES (?, ?, ?)',
            [1, 'John Doe', 25],
            function () {
              document.getElementById('status').textContent = 'Added John Doe';
            }
          );
        });
      });

      document.getElementById('updateRecord').addEventListener('click', function () {
        updateRecord(1, 'Jane Doe', 26);
      });

      function updateRecord(id, newName, newAge) {
        db.transaction(function (tx) {
          tx.executeSql(
            'UPDATE users SET name = ?, age = ? WHERE id = ?',
            [newName, newAge, id],
            function (tx, result) {
              document.getElementById('status').textContent =
                result.rowsAffected
                  ? 'Updated to ' + newName
                  : 'No row found — add a record first';
            },
            function (tx, error) {
              document.getElementById('status').textContent = 'Error: ' + error.message;
              return true;
            }
          );
        });
      }
    }
  </script>
</body>
</html>
Try It Yourself

How It Works

Click Add Record to seed id 1, then Update Record changes name and age. Status text on the page gives immediate feedback either way.

Use Cases

Real-world scenarios where changing an existing row is exactly what you need.

1. Profile Editing

Update display name, bio, or avatar URL fields when a user edits their account.

Example: UPDATE users SET name = ? WHERE id = ?.

2. App Settings

Persist theme, font size, or language preferences the user changes locally.

Example: UPDATE settings SET theme = ? WHERE user_id = ?.

3. Offline Sync Flags

Set synced = 1 after successfully uploading a locally-created row to a server.

Example: UPDATE queue SET synced = 1 WHERE id = ?.

4. Cart Quantities

Adjust qty when a shopper increases or decreases how many items they want.

Example: UPDATE cart SET qty = ? WHERE product_id = ?.

5. Cache Refresh

Overwrite a stale cached value with fresh data instead of deleting and re-inserting the row.

Example: UPDATE cache SET value = ?, updated_at = ? WHERE key = ?.

6. Legacy Maintenance

Patch existing Web SQL data in older mobile web apps still running in the wild.

Example: a support script correcting bad values in an old dataset.

Pro Tip: pair every update with a SELECT during development so you can confirm the row landed with the values you expected.

Advantages

Why the standard SQL UPDATE pattern is worth learning, even in a deprecated API.

  1. 1. Precise Targeting

    WHERE changes exactly the rows you specify—nothing implicit.

  2. 2. Safe by Default

    ? bindings sanitize new values automatically, avoiding SQL injection.

  3. 3. Auditable Results

    rowsAffected tells you exactly how many rows changed—no guessing.

  4. 4. Transactional Atomicity

    Wrapped in db.transaction(), related statements succeed or fail together.

Pro Tip: this exact pattern—WHERE, a minimal SET list, bound parameters, and checking affected rows—transfers directly to IndexedDB, SQLite, and server-side SQL.

Usage Tips

Follow these practices to write safe, predictable updates.

  1. 1. Preview With SELECT First

    Run the equivalent SELECT ... WHERE ... to confirm which rows will change before you update.

  2. 2. Always Check rowsAffected

    Zero means no match—update your UI to say “not found,” not “saved.”

  3. 3. Bind Every Dynamic Value

    Use ? placeholders for new values and ids—never build SQL with string concatenation.

  4. 4. List Only Columns That Change

    Keep the SET clause short—every extra column is one more thing that could overwrite good data by mistake.

  5. 5. Plan Your Migration to IndexedDB

    Web SQL is deprecated—treat new features as an opportunity to move to IndexedDB.

Pro Tip: log every update’s SQL, bound values, and rowsAffected during development—it turns “why didn’t that save?” bugs into a quick log lookup.

Common Pitfalls

Avoid these mistakes when changing rows with Web SQL.

  1. 1. UPDATE Without WHERE

    Forgetting the condition changes every row in the table instantly, with no confirmation.

    → Always double-check for a WHERE clause before running an update.

  2. 2. Concatenating SQL Strings

    Building queries with string concatenation opens the door to SQL injection.

    → Bind every dynamic value with ? placeholders instead.

  3. 3. Ignoring rowsAffected

    Treating every callback as success hides “row not found” cases from your users.

    → Check result.rowsAffected and branch your UI message accordingly.

  4. 4. Confusing UPDATE With INSERT OR REPLACE

    UPDATE only changes columns you list and does nothing if the row is missing; INSERT OR REPLACE deletes and recreates the entire row, resetting any column you forget to supply.

    → Use UPDATE to edit specific fields on a known row, and INSERT OR REPLACE only for full-row upserts.

  5. 5. Assuming Web SQL Works in Modern Chrome

    Chrome removed Web SQL in version 97—code that assumes openDatabase exists will crash.

    → Feature-detect with if (window.openDatabase) before running any Web SQL code.

Pro Tip: when in doubt, run the same condition as a SELECT first—if the preview looks right, the update will too.

🧠 How Web SQL UPDATE Works

1

Find rows

WHERE id = ? selects matching rows.

Filter
2

Set new values

SET name = ?, age = ? assigns columns.

Modify
3

Run UPDATE & commit

executeSql writes the change; the transaction commits it.

Save
=

Row updated

rowsAffected tells you how many rows changed.

Notes

  • Web SQL is deprecated and removed from modern Chrome—use IndexedDB for any new project.
  • Always include WHERE unless you intentionally mean to update every row.
  • Check rowsAffected—zero means no match, not necessarily an error.
  • Bind all dynamic values with ? placeholders—never string-concatenate SQL.
  • UPDATE cannot create new rows—use INSERT first, or INSERT OR REPLACE for an upsert.
  • Combine with SELECT to read back the updated values and confirm the change.

Quick Takeaway: Web SQL is deprecated—practice UPDATE here to learn the pattern, then apply the same WHERE + bindings + rowsAffected habits in IndexedDB and other SQL databases.

Browser Support

Web SQL was never implemented in Firefox or Internet Explorer. Chrome and other Chromium browsers removed it in Chrome 97. Only older Safari versions historically supported it. Feature-detect with window.openDatabase before running any demo or legacy code.

Deprecated

Web SQL API

Web SQL is not part of any current web standard. Modern Chrome, Edge, and Opera have removed it entirely; Firefox never implemented it. Treat this tutorial as educational for legacy maintenance only.

Legacy Not in modern browsers
Google Chrome Removed in Chrome 97+
Removed
Mozilla Firefox Never implemented
Not supported
Apple Safari Legacy versions only
Legacy
Microsoft Edge Chromium-based · removed
Removed
Internet Explorer Never implemented
Not supported
Opera Chromium-based · removed
Removed
Web SQL API Deprecated

Bottom line: Do not build new features on Web SQL. For cross-browser client-side storage today, use IndexedDB.

Wrap Up

🎉 Conclusion

Updating records with Web SQL means running UPDATE ... SET ... WHERE ... inside db.transaction, binding values safely with ?, and checking rowsAffected to confirm the right row changed.

You have now covered the full Web SQL CRUD series—INSERT, SELECT, UPDATE, and DELETE. Although Web SQL is deprecated, the same patterns carry forward directly into IndexedDB or a server-side database.

Practice the five examples above, then continue to Web Workers to run scripts off the main thread.

💡 Best Practices

✅ Do

  • Use WHERE to target specific rows
  • Bind values with ? placeholders
  • Check result.rowsAffected after every update
  • Validate form input before writing to the database
  • Handle error callbacks and return true to roll back
  • Prefer IndexedDB for new projects

❌ Don’t

  • Omit WHERE unless you mean to update all rows
  • Concatenate user input into SQL strings
  • Assume success when rowsAffected is 0
  • Use UPDATE to create rows that do not exist
  • Confuse UPDATE with a full-row INSERT OR REPLACE
  • Build new features on Web SQL in 2026

Key Takeaways

Knowledge Unlocked

Five things to remember about Web SQL UPDATE

Use these points when modifying rows in a client-side database.

5
Core concepts
🎯 02

WHERE

Target id.

Filter
🔒 03

? bindings

Safe params.

Security
🔢 04

rowsAffected

Verify hit.

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 UPDATE statement and a WHERE clause. Bind new values and the target id with ? placeholders: UPDATE users SET name = ?, age = ? WHERE id = ?
Standard SQL: UPDATE table_name SET column1 = ?, column2 = ? WHERE condition. Always include a WHERE clause when updating specific rows—without it, every row in the table is updated.
Check result.rowsAffected in the success callback. If it is 0, no row matched your WHERE clause (wrong id, or the row does not exist yet).
Web SQL requires all executeSql calls inside db.transaction(). Transactions keep changes atomic—if a later statement fails, earlier changes in the same 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.
UPDATE changes columns on existing rows matched by WHERE—the row must already exist. INSERT OR REPLACE inserts a new row or replaces the entire row when the primary key exists. Use UPDATE when you only want to change specific fields on a row you know is there.

Did you Know? 🔊

UPDATE table_name SET col = ? without a WHERE clause changes every row in the table—the SET list decides which columns change, and rowsAffected is the only way to confirm how many rows actually did. Because Web SQL is deprecated, treat every UPDATE you write here as a rehearsal for the same pattern in IndexedDB.

Continue to Web Workers API

Now that you can create, read, update, and delete rows, learn how to keep heavy work off the main thread.

Web Workers API 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.

9 people found this page helpful