Skip to main content
A computed column exposes data generated from other columns by a scalar expression included in the column definition. A stored computed column (set with the STORED SQL keyword) is calculated when a row is inserted or updated, and stores the resulting value of the scalar expression in the primary index similar to a non-computed column. A virtual computed column (set with the VIRTUAL SQL keyword) is not stored, and the value of the scalar expression is computed at query-time as needed.

Why use computed columns?

Computed columns are especially useful when used with JSONB columns or secondary indexes.
  • JSONB columns are used for storing semi-structured JSONB data. When the table’s primary information is stored in JSONB, it’s useful to index a particular field of the JSONB document. In particular, computed columns allow for the following use case: a two-column table with a PRIMARY KEY column and a payload JSONB column, whose primary key is computed from a field of the payload column. This alleviates the need to manually separate your primary keys from your JSON blobs. For more information, see Create a table with a JSONB column and a stored computed column.
  • Secondary indexes can be created on computed columns, which is especially useful when a table is frequently sorted. See Create a table with a secondary index on a computed column.

Considerations

Computed columns:
  • Cannot be used to generate other computed columns.
  • Behave like any other column, with the exception that they cannot be written to directly.
  • Are mutually exclusive with DEFAULT and ON UPDATE expressions.
  • Can be used in FOREIGN KEY constraints, but are restricted to the following subset of supported options. This restriction is necessary because we cannot allow the computed column value to change.
    • ON UPDATE (NO ACTION|RESTRICT)
    • ON DELETE (NO ACTION|RESTRICT|CASCADE)
Virtual computed columns:
  • Are not stored in the table’s primary index.
  • Are recomputed as the column data in the expression changes.
  • Cannot be used as part of a FAMILY definition, in CHECK constraints, or in FOREIGN KEY constraints.
  • Cannot be a foreign key reference.
  • Cannot be stored in indexes.
  • Can be index columns.
Once a computed column is created, you cannot directly alter the formula. To make modifications to a computed column’s formula, see Alter the formula for a computed column.

Define a computed column

To define a stored computed column, use the following syntax:
To define a virtual computed column, use the following syntax:
For compatibility with PostgreSQL, CockroachDB also supports creating stored computed columns with the syntax column_name <type> GENERATED ALWAYS AS (<expr) STORED.

Examples

Create a table with a stored computed column

In this example, let’s create a simple table with a computed column:
Then, insert a few rows of data:
The full_name column is computed from the first_name and last_name columns without the need to define a view.

Create a table with a JSONB column and a stored computed column

In this example, create a table with a JSONB column and a stored computed column:
Create a compute column after you create a table:
Then, insert a few rows of data:
The primary key id is computed as a field from the profile column. Additionally the age column is computed from the profile column data as well. This example shows how add a stored computed column with a coerced type:

Create a virtual computed column using JSONB data

In this example, create a table with a JSONB column and virtual computed columns:
Then, insert a few rows of data:
The virtual column full_name is computed as a field from the profile column’s data. The first name and last name are concatenated and separated by a single whitespace character using the concat_ws string function. The virtual column birthday is parsed as a TIMESTAMP value from the profile column’s birthdate string value. The parse_timestamp function is used to parse strings in TIMESTAMP format.

Create a table with a secondary index on a computed column

In this example, create a table with a virtual computed column and an index on that column:
Then, insert a few rows a data:
Now, run a query using the secondary index:
The athlete with the highest combined score of 61.833 is Simone Biles.

Add a computed column to an existing table

In this example, create a table:
Then, insert a row of data:
Now add another virtual computed column to the table:
The d column is added to the table and computed from the a column divided by 2.
For more information, see ADD COLUMN.

Convert a computed column into a regular column

You can convert a stored, computed column into a regular column by using ALTER TABLE. In this example, create a simple table with a computed column:
Then, insert a few rows of data:
The full_name column is computed from the first_name and last_name columns without the need to define a view. You can view the column details with the SHOW COLUMNS statement:
Now, convert the computed column (full_name) to a regular column:
Check that the computed column was converted:
The computed column is now a regular column and can be updated as such:

Alter the formula for a computed column

To alter the formula for a computed column, you must DROP and ADD the column back with the new definition. Take the following table for instance:
Add a computed column d:
If you try to alter it, you’ll get an error:
However, you can drop it and then add it with the new definition:
If the computed column controls row locality in a REGIONAL BY ROW table (for example, using a custom crdb_internal_region column with REGIONAL BY ROW AS), you can change its expression by following the steps in Modify the region column or its expression.

Known limitations

  • The sql.guardrails.max_row_size_err cluster setting misses large rows caused by indexed virtual computed columns. This is because the guardrail only checks the size of primary key rows, not secondary index rows.

See also