> ## Documentation Index
> Fetch the complete documentation index at: https://cockroachlabs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Computed Columns

export const InternalLink = ({version, path = "", children, ...props}) => {
  let detectedVersion = version || "stable";
  if (typeof window !== 'undefined' && !version) {
    const match = window.location.pathname.match(/\/docs\/([^/]+)/);
    if (match) {
      detectedVersion = match[1];
    }
  }
  const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
  return <a href={`/docs/${detectedVersion}/${normalizedPath}`} {...props}>
      {children}
    </a>;
};

A *computed column* exposes data generated from other columns by a <InternalLink path="scalar-expressions">scalar expression</InternalLink> 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 <InternalLink path="jsonb">`JSONB`</InternalLink> columns or <InternalLink path="indexes">secondary indexes</InternalLink>.

* **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](#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](#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 <InternalLink path="default-value">`DEFAULT`</InternalLink> and <InternalLink path="create-table#on-update-expressions">`ON UPDATE`</InternalLink> expressions.
* Can be used in <InternalLink path="foreign-key">`FOREIGN KEY`</InternalLink> 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 <InternalLink path="foreign-key">foreign key</InternalLink> 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](#alter-the-formula-for-a-computed-column).

## Define a computed column

To define a stored computed column, use the following syntax:

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
column_name <type> AS (<expr) STORED
```

To define a virtual computed column, use the following syntax:

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
column_name <type> AS (<expr) VIRTUAL
```

| Parameter      | Description                                                                                                                                                                                                                                                                          |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `column\_name` | The <InternalLink path="keywords-and-identifiers#identifiers">name</InternalLink> of the computed column.                                                                                                                                                                            |
| \`\`           | The <InternalLink path="data-types">data type</InternalLink> of the computed column.                                                                                                                                                                                                 |
| \`\`           | The <InternalLink path="functions-and-operators#function-volatility">immutable</InternalLink><InternalLink path="scalar-expressions">scalar expression</InternalLink> used to compute column values. You cannot use functions such as `now()` or `nextval()` that are not immutable. |
| `STORED`       | *(Required for stored computed columns)* The computed column is stored alongside other columns.                                                                                                                                                                                      |
| `VIRTUAL`      | *(Required for virtual columns)* The computed column is virtual, meaning the column data is not stored in the table's primary index.                                                                                                                                                 |

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:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> CREATE TABLE users (
        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
        city STRING,
        first_name STRING,
        last_name STRING,
        full_name STRING AS (CONCAT(first_name, ' ', last_name)) STORED,
        address STRING,
        credit_card STRING,
        dl STRING UNIQUE CHECK (LENGTH(dl) < 8)
);
```

Then, insert a few rows of data:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> INSERT INTO users (first_name, last_name) VALUES
    ('Lola', 'McDog'),
    ('Carl', 'Kimball'),
    ('Ernie', 'Narayan');
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SELECT * FROM users;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
                   id                  | city | first_name | last_name |   full_name   | address | credit_card |  dl
+--------------------------------------+------+------------+-----------+---------------+---------+-------------+------+
  5740da29-cc0c-47af-921c-b275d21d4c76 | NULL | Ernie      | Narayan   | Ernie Narayan | NULL    | NULL        | NULL
  e7e0b748-9194-4d71-9343-cd65218848f0 | NULL | Lola       | McDog     | Lola McDog    | NULL    | NULL        | NULL
  f00e4715-8ca7-4d5a-8de5-ef1d5d8092f3 | NULL | Carl       | Kimball   | Carl Kimball  | NULL    | NULL        | NULL
(3 rows)
```

The `full_name` column is computed from the `first_name` and `last_name` columns without the need to define a <InternalLink path="views">view</InternalLink>.

### 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:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> CREATE TABLE student_profiles (
    id STRING PRIMARY KEY AS (profile->>'id') STORED,
    profile JSONB
);
```

Create a compute column after you create a table:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> ALTER TABLE student_profiles ADD COLUMN age INT AS ( (profile->>'age')::INT) STORED;
```

Then, insert a few rows of data:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> INSERT INTO student_profiles (profile) VALUES
    ('{"id": "d78236", "name": "Arthur Read", "age": "16", "school": "PVPHS", "credits": 120, "sports": "none"}'),
    ('{"name": "Buster Bunny", "age": "15", "id": "f98112", "school": "THS", "credits": 67, "clubs": "MUN"}'),
    ('{"name": "Ernie Narayan", "school" : "Brooklyn Tech", "id": "t63512", "sports": "Track and Field", "clubs": "Chess"}');
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SELECT * FROM student_profiles;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
+--------+---------------------------------------------------------------------------------------------------------------------+------+
|   id   |                                                       profile                                                       | age  |
---------+---------------------------------------------------------------------------------------------------------------------+------+
| d78236 | {"age": "16", "credits": 120, "id": "d78236", "name": "Arthur Read", "school": "PVPHS", "sports": "none"}           |   16 |
| f98112 | {"age": "15", "clubs": "MUN", "credits": 67, "id": "f98112", "name": "Buster Bunny", "school": "THS"}               |   15 |
| t63512 | {"clubs": "Chess", "id": "t63512", "name": "Ernie Narayan", "school": "Brooklyn Tech", "sports": "Track and Field"} | NULL |
+--------+---------------------------------------------------------------------------------------------------------------------+------|
```

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 <InternalLink path="scalar-expressions#explicit-type-coercions">coerced type</InternalLink>:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CREATE TABLE json_data (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    json_info JSONB
);
INSERT INTO json_data (json_info) VALUES ('{"amount": "123.45"}');
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
ALTER TABLE json_data ADD COLUMN amount DECIMAL AS ((json_info->>'amount')::DECIMAL) STORED;
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
SELECT * FROM json_data;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
                   id                  |      json_info       | amount
---------------------------------------+----------------------+---------
  e7c3d706-1367-4d77-bfb4-386dfdeb10f9 | {"amount": "123.45"} | 123.45
(1 row)
```

### Create a virtual computed column using `JSONB` data

In this example, create a table with a `JSONB` column and virtual computed columns:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> CREATE TABLE student_profiles (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    profile JSONB,
    full_name STRING AS (concat_ws(' ',profile->>'firstName', profile->>'lastName')) VIRTUAL,
    birthday TIMESTAMP AS (parse_timestamp(profile->>'birthdate')) VIRTUAL
);
```

Then, insert a few rows of data:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> INSERT INTO student_profiles (profile) VALUES
    ('{"id": "d78236", "firstName": "Arthur", "lastName": "Read", "birthdate": "2010-01-25", "school": "PVPHS", "credits": 120, "sports": "none"}'),
    ('{"firstName": "Buster", "lastName": "Bunny", "birthdate": "2011-11-07", "id": "f98112", "school": "THS", "credits": 67, "clubs": "MUN"}'),
    ('{"firstName": "Ernie", "lastName": "Narayan", "school" : "Brooklyn Tech", "id": "t63512", "sports": "Track and Field", "clubs": "Chess"}');
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SELECT * FROM student_profiles;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
                   id                  |                                                                   profile                                                                   |   full_name   |      birthday
---------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------+---------------+----------------------
  0e420282-105d-473b-83e2-3b082e7033e4 | {"birthdate": "2011-11-07", "clubs": "MUN", "credits": 67, "firstName": "Buster", "id": "f98112", "lastName": "Bunny", "school": "THS"}     | Buster Bunny  | 2011-11-07 00:00:00
  6e9b77cd-ec67-41ae-b346-7b3d89902c72 | {"birthdate": "2010-01-25", "credits": 120, "firstName": "Arthur", "id": "d78236", "lastName": "Read", "school": "PVPHS", "sports": "none"} | Arthur Read   | 2010-01-25 00:00:00
  f74b21e3-dc1e-49b7-a648-3c9b9024a70f | {"clubs": "Chess", "firstName": "Ernie", "id": "t63512", "lastName": "Narayan", "school": "Brooklyn Tech", "sports": "Track and Field"}     | Ernie Narayan | NULL
(3 rows)

Time: 2ms total (execution 2ms / network 0ms)
```

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 <InternalLink path="functions-and-operators#string-and-byte-functions">`concat_ws` string function</InternalLink>.

The virtual column `birthday` is parsed as a `TIMESTAMP` value from the `profile` column's `birthdate` string value. The <InternalLink path="functions-and-operators">`parse_timestamp` function</InternalLink> 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:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> CREATE TABLE gymnastics (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    athlete STRING,
    vault DECIMAL,
    bars DECIMAL,
    beam DECIMAL,
    floor DECIMAL,
    combined_score DECIMAL AS (vault + bars + beam + floor) VIRTUAL,
    INDEX total (combined_score DESC)
  );
```

Then, insert a few rows a data:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> INSERT INTO gymnastics (athlete, vault, bars, beam, floor) VALUES
    ('Simone Biles', 15.933, 14.800, 15.300, 15.800),
    ('Gabby Douglas', 0, 15.766, 0, 0),
    ('Laurie Hernandez', 15.100, 0, 15.233, 14.833),
    ('Madison Kocian', 0, 15.933, 0, 0),
    ('Aly Raisman', 15.833, 0, 15.000, 15.366);
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SELECT * FROM gymnastics;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
+--------------------------------------+------------------+--------+--------+--------+--------+----------------+
|                  id                  |     athlete      | vault  |  bars  |  beam  | floor  | combined_score |
+--------------------------------------+------------------+--------+--------+--------+--------+----------------+
| 3fe11371-6a6a-49de-bbef-a8dd16560fac | Aly Raisman      | 15.833 |      0 | 15.000 | 15.366 |         46.199 |
| 56055a70-b4c7-4522-909b-8f3674b705e5 | Madison Kocian   |      0 | 15.933 |      0 |      0 |         15.933 |
| 69f73fd1-da34-48bf-aff8-71296ce4c2c7 | Gabby Douglas    |      0 | 15.766 |      0 |      0 |         15.766 |
| 8a7b730b-668d-4845-8d25-48bda25114d6 | Laurie Hernandez | 15.100 |      0 | 15.233 | 14.833 |         45.166 |
| b2c5ca80-21c2-4853-9178-b96ce220ea4d | Simone Biles     | 15.933 | 14.800 | 15.300 | 15.800 |         61.833 |
+--------------------------------------+------------------+--------+--------+--------+--------+----------------+
```

Now, run a query using the secondary index:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SELECT athlete, combined_score FROM gymnastics ORDER BY combined_score DESC;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
+------------------+----------------+
|     athlete      | combined_score |
+------------------+----------------+
| Simone Biles     |         61.833 |
| Aly Raisman      |         46.199 |
| Laurie Hernandez |         45.166 |
| Madison Kocian   |         15.933 |
| Gabby Douglas    |         15.766 |
+------------------+----------------+
```

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:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> CREATE TABLE x (
    a INT NULL,
    b INT NULL AS (a * 2) STORED,
    c INT NULL AS (a + 4) STORED,
    FAMILY "primary" (a, b, rowid, c)
  );
```

Then, insert a row of data:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> INSERT INTO x VALUES (6);
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SELECT * FROM x;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
+---+----+----+
| a | b  | c  |
+---+----+----+
| 6 | 12 | 10 |
+---+----+----+
(1 row)
```

Now add another virtual computed column to the table:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> ALTER TABLE x ADD COLUMN d INT AS (a // 2) VIRTUAL;
```

The `d` column is added to the table and computed from the `a` column divided by 2.

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SELECT * FROM x;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
+---+----+----+---+
| a | b  | c  | d |
+---+----+----+---+
| 6 | 12 | 10 | 3 |
+---+----+----+---+
(1 row)
```

For more information, see <InternalLink path="alter-table#add-column">`ADD COLUMN`</InternalLink>.

### 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:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> CREATE TABLE office_dogs (
    id INT PRIMARY KEY,
    first_name STRING,
    last_name STRING,
    full_name STRING AS (CONCAT(first_name, ' ', last_name)) STORED
  );
```

Then, insert a few rows of data:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> INSERT INTO office_dogs (id, first_name, last_name) VALUES
    (1, 'Petee', 'Hirata'),
    (2, 'Carl', 'Kimball'),
    (3, 'Ernie', 'Narayan');
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SELECT * FROM office_dogs;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
+----+------------+-----------+---------------+
| id | first_name | last_name |   full_name   |
+----+------------+-----------+---------------+
|  1 | Petee      | Hirata    | Petee Hirata  |
|  2 | Carl       | Kimball   | Carl Kimball  |
|  3 | Ernie      | Narayan   | Ernie Narayan |
+----+------------+-----------+---------------+
(3 rows)
```

The `full_name` column is computed from the `first_name` and `last_name` columns without the need to define a <InternalLink path="views">view</InternalLink>. You can view the column details with the <InternalLink path="show-columns">`SHOW COLUMNS`</InternalLink> statement:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SHOW COLUMNS FROM office_dogs;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
+-------------+-----------+-------------+----------------+------------------------------------+-------------+
| column_name | data_type | is_nullable | column_default |       generation_expression        |   indices   |
+-------------+-----------+-------------+----------------+------------------------------------+-------------+
| id          | INT       |    false    | NULL           |                                    | {"primary"} |
| first_name  | STRING    |    true     | NULL           |                                    | {}          |
| last_name   | STRING    |    true     | NULL           |                                    | {}          |
| full_name   | STRING    |    true     | NULL           | concat(first_name, ' ', last_name) | {}          |
+-------------+-----------+-------------+----------------+------------------------------------+-------------+
(4 rows)
```

Now, convert the computed column (`full_name`) to a regular column:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> ALTER TABLE office_dogs ALTER COLUMN full_name DROP STORED;
```

Check that the computed column was converted:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SHOW COLUMNS FROM office_dogs;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
+-------------+-----------+-------------+----------------+-----------------------+-------------+
| column_name | data_type | is_nullable | column_default | generation_expression |   indices   |
+-------------+-----------+-------------+----------------+-----------------------+-------------+
| id          | INT       |    false    | NULL           |                       | {"primary"} |
| first_name  | STRING    |    true     | NULL           |                       | {}          |
| last_name   | STRING    |    true     | NULL           |                       | {}          |
| full_name   | STRING    |    true     | NULL           |                       | {}          |
+-------------+-----------+-------------+----------------+-----------------------+-------------+
(4 rows)
```

The computed column is now a regular column and can be updated as such:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> INSERT INTO office_dogs (id, first_name, last_name, full_name) VALUES (4, 'Lola', 'McDog', 'This is not computed');
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SELECT * FROM office_dogs;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
+----+------------+-----------+----------------------+
| id | first_name | last_name |      full_name       |
+----+------------+-----------+----------------------+
|  1 | Petee      | Hirata    | Petee Hirata         |
|  2 | Carl       | Kimball   | Carl Kimball         |
|  3 | Ernie      | Narayan   | Ernie Narayan        |
|  4 | Lola       | McDog     | This is not computed |
+----+------------+-----------+----------------------+
(4 rows)
```

### Alter the formula for a computed column

To alter the formula for a computed column, you must <InternalLink path="alter-table#drop-column">`DROP`</InternalLink> and <InternalLink path="alter-table#add-column">`ADD`</InternalLink> the column back with the new definition. Take the following table for instance:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> CREATE TABLE x (
a INT NULL,
b INT NULL AS (a * 2) STORED,
c INT NULL AS (a + 4) STORED,
FAMILY "primary" (a, b, rowid, c)
);
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CREATE TABLE

Time: 4ms total (execution 4ms / network 0ms)
```

Add a computed column `d`:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> ALTER TABLE x ADD COLUMN d INT AS (a // 2) STORED;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
ALTER TABLE

Time: 199ms total (execution 199ms / network 0ms)
```

If you try to alter it, you'll get an error:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> ALTER TABLE x ALTER COLUMN d INT AS (a // 3) STORED;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
invalid syntax: statement ignored: at or near "int": syntax error
SQLSTATE: 42601
DETAIL: source SQL:
ALTER TABLE x ALTER COLUMN d INT AS (a // 3) STORED
                             ^
HINT: try \h ALTER TABLE
```

However, you can drop it and then add it with the new definition:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
> SET sql_safe_updates = false;
> ALTER TABLE x DROP COLUMN d;
> ALTER TABLE x ADD COLUMN d INT AS (a // 3) STORED;
> SET sql_safe_updates = true;
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
SET

Time: 1ms total (execution 0ms / network 0ms)

ALTER TABLE

Time: 195ms total (execution 195ms / network 0ms)

ALTER TABLE

Time: 186ms total (execution 185ms / network 0ms)

SET

Time: 0ms total (execution 0ms / network 0ms)
```

<Note>
  If the computed column controls row locality in a <InternalLink path="table-localities#regional-by-row-tables">`REGIONAL BY ROW`</InternalLink> table (for example, using a custom <InternalLink path="alter-table">`crdb_internal_region`</InternalLink> column with `REGIONAL BY ROW AS`), you can change its expression by following the steps in <InternalLink path="alter-table">Modify the region column or its expression</InternalLink>.
</Note>

## Known limitations

* The `sql.guardrails.max_row_size_err` <InternalLink path="cluster-settings">cluster setting</InternalLink> 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

* <InternalLink path="scalar-expressions">Scalar Expressions</InternalLink>
* <InternalLink path="information-schema">Information Schema</InternalLink>
* <InternalLink path="create-table">`CREATE TABLE`</InternalLink>
* <InternalLink path="jsonb">`JSONB`</InternalLink>
