Skip to main content
The UPDATE statement updates rows in a table.
If you update a row that contains a column referenced by a foreign key constraint and has an ON UPDATE action, all of the dependent rows will also be updated.

Required privileges

The user must have the SELECT and UPDATE privileges on the table.

Synopsis

update syntax diagram

Parameters

Force index selection for updates

By using the explicit index annotation (also known as “index hinting”), you can override CockroachDB’s index selection and use a specific index for updating rows of a named table.
Index selection can impact performance, but does not change the result of a query. The syntax to force an update for a specific index is:
This is equivalent to the longer expression:
To view how the index hint modifies the query plan that CockroachDB follows for updating rows, use an EXPLAIN (OPT) statement. To see all indexes available on a table, use SHOW INDEXES. For examples, see Update with index hints.

Reference other tables in an update

To reference values from a table other than the table being updated, add a FROM clause that specifies one or more tables in the cluster. Values from tables specified in a FROM clause can be used in UPDATE expressions, and in RETURNING and WHERE clauses. When executing an UPDATE query with a FROM clause, CockroachDB joins the target table (i.e., the table being updated) to the tables referenced in the FROM clause. The output of this join should have the same number of rows as the rows being updated in the target table, as CockroachDB uses a single row from the join output to update a given row in the target table. If the join produces more rows than the rows being updated in the target table, there is no way to predict which row from the join output will be used to update a row in the target table. For an example, see Update using values from a different table.

Bulk-update data

To update a large number of rows (i.e., tens of thousands of rows or more), we recommend iteratively updating subsets of the rows that you want to update, until all of the rows have been updated. You can write a script to do this, or you can write a loop into your application. For guidance and an example, see Bulk-update Data.

Examples

Setup

To follow along, run cockroach demo to start a temporary, in-memory cluster with the movr sample dataset preloaded:

Update a single column in a single row

Update multiple columns in a single row

Update using SELECT statement

Update with default values

Update using values from a different table

Update all rows

If you do not use the WHERE clause to specify the rows to be updated, the values for all rows will be updated.
If the sql_safe_updates session variable is set to true, the client will prevent the update. sql_safe_updates is set to true by default.
You can use a SET statement to set session variables.

Update and return values

In this example, the RETURNING clause returns the id value of the row updated. The language-specific versions assume that you have installed the relevant client drivers.
When a driver provides a query() method for statements that return results and an exec() method for statements that do not (e.g., Go), it’s likely necessary to use the query() method for UPDATE statements with RETURNING.

Update with index hints

Suppose that you create a multi-column index on the users table with the name and city columns.
Now suppose you want to update a couple rows in the table, based on their contents. You can use the EXPLAIN (OPT) command to see how the cost-based optimizer decides to perform the UPDATE statement:
The output of the EXPLAIN statement shows that the optimizer scans the newly-created users_name_city_idx index when performing the update. This makes sense, as you are performing an update based on the name column. Although users_name_city_idx is likely the most efficient index for the table scan, you may want to assess the performance difference between scanning on users_name_city_idx and scanning on the primary index. You can provide an index hint (i.e., force the index selection) to use the primary key of the users table:

Limit the size of rows

To help you avoid failures arising from misbehaving applications that bloat the size of rows, you can specify the behavior when a row or individual column family larger than a specified size is written to the database. Use the cluster settings sql.guardrails.max_row_size_log to discover large rows and sql.guardrails.max_row_size_err to reject large rows. When you write a row that exceeds sql.guardrails.max_row_size_log:
  • INSERT, UPSERT, UPDATE, CREATE TABLE AS, CREATE INDEX, ALTER TABLE, ALTER INDEX, IMPORT, or RESTORE statements will log a LargeRow to the SQL_PERF channel.
  • SELECT, DELETE, TRUNCATE, and DROP are not affected.
When you write a row that exceeds sql.guardrails.max_row_size_err:
  • INSERT, UPSERT, and UPDATE statements will fail with a code 54000 (program_limit_exceeded) error.
  • CREATE TABLE AS, CREATE INDEX, ALTER TABLE, ALTER INDEX, IMPORT, and RESTORE statements will log a LargeRowInternal event to the SQL_INTERNAL_PERF channel.
  • SELECT, DELETE, TRUNCATE, and DROP are not affected.
You cannot update existing rows that violate the limit unless the update shrinks the size of the row below the limit. You can select, delete, alter, back up, and restore such rows. We recommend using the accompanying setting sql.guardrails.max_row_size_log in conjunction with SELECT pg_column_size() queries to detect and fix any existing large rows before lowering sql.guardrails.max_row_size_err.

See also