Drizzle Update Explained: With Code Examples

Updating data in Drizzle ORM stays predictable and fully type-safe, whether you’re modifying a single row, updating multiple records, or running advanced logic using conditions, limits, and CTE-based updates.

Each operation flows the same way — define what to update, specify the condition, and let Drizzle handle the SQL underneath with complete schema awareness.

Before working with updates in Drizzle ORM, ensure the data you need is already created. If you haven’t set up your insert flow yet, start there first.

Update One

To update a single row in Drizzle ORM, you call db.update(), pass the table, define the fields in .set(), and target the row with a typed where condition. Drizzle ensures every column and value matches your schema before executing the query.

Example:

const updatedUser = await db
  .update(users)
  .set({ email: "abc@a.com" })
  .where(eq(users.email, "react@frontend.com"))
  .returning();

console.log("Updated Record:", updatedUser);

Update Many

Updating multiple rows in Drizzle ORM follows the same predictable flow as a single update — you define the fields you want to change, set your condition, and Drizzle applies the update to every matching record.

Because the entire operation is tied to your schema, the bulk update stays type-safe, consistent, and easy to maintain across your codebase.

Example:

const updatedUsers = await db
  .update(users)
  .set({ status: "inactive" })
  .where(inArray(users.id, [2, 4, 6]))
  .returning();

console.log("Updated Records:", updatedUsers);

Update and Return

When you need the updated data immediately after an update, Drizzle ORM makes it simple. You define the fields to modify, target the row with a typed condition, and append .returning() to get the updated record back in the same operation.

const updatedUser = await db
  .update(users)
  .set({ name: "Sharukhan" })
  .where(eq(users.id, 1))
  .returning();

console.log("Updated Record:", updatedUser);

Conditional Updation

Conditional updates in Drizzle ORM let you modify a row only when certain criteria are met. You define the fields to change inside .set(), add your condition in .where(), and Drizzle ensures the update happens only when the condition evaluates to true. This keeps your update logic precise and prevents accidental changes to records that don’t meet your requirements.

Example:

const updatedUser = await db
  .update(users)
  .set({ badge: "regular" })
  .where(
    and(
      eq(users.status, "active"),
      gt(users.loginCount, 5)
    )
  )
  .returning();

console.log("Conditional Update:", updatedUser);

What is the ‘with update’ clause?

In SQL, the WITH clause (also known as Common Table Expressions — CTEs) lets you build temporary result sets that only exist during a single query.

It allows you to:

  • Pre-calculate values
  • Select specific rows
  • Filter or rank records
  • Join related tables
  • Then feed that result into an UPDATE query

Example:

const overdue = db.$with("overdue_users").as(
  db.select({ id: users.id }).from(users)
    .where(lt(users.lastLogin, ninetyDaysAgo))
);

const result = await db
  .with(overdue)
  .update(users)
  .set({ status: "inactive" })
  .where(inArray(users.id, overdue.select({ id: overdue.id })))
  .returning();

Summary

By now, you’ve covered every core update pattern in Drizzle ORM — updating a single row, updating many records, returning modified values, applying conditional logic, and even performing advanced updates using CTEs with the WITH clause.

You now have a complete, type-safe workflow for handling updates across simple changes, bulk operations, and complex rule-based updates.

Author

Sharukhan is the founder of Tecktol. He has worked as a software engineer specializing in full-stack web development.