Generated columns¶
It is possible to define columns whose value is computed by applying a generation expression in the context of the current row. The generation expression can reference the values of other columns.
Table of contents
Generation expressions¶
Generated columns are defined by providing a generation expression. Providing a data type is optional. It is inferred by the return type of the supplied expression if omitted:
cr> CREATE TABLE computed (
... dividend double precision,
... divisor double precision,
... quotient GENERATED ALWAYS AS (dividend / divisor)
... );
CREATE OK, 1 row affected (... sec)
See also
For a full syntax description, see CREATE TABLE.
Generated columns are read-only. Their values are computed as needed for every
INSERT
and UPDATE
operation.
For example:
cr> INSERT INTO computed (dividend, divisor)
... VALUES (1.7, 1.5), (0.0, 10.0);
INSERT OK, 2 rows affected (... sec)
The generated column is now filled with the computed value:
cr> SELECT dividend, divisor, quotient
... FROM computed
... ORDER BY quotient;
+----------+---------+--------------------+
| dividend | divisor | quotient |
+----------+---------+--------------------+
| 0.0 | 10.0 | 0.0 |
| 1.7 | 1.5 | 1.1333333333333333 |
+----------+---------+--------------------+
SELECT 2 rows in set (... sec)
The generation expression is evaluated in the context of the current row. This means that you can compute a generated value from the values of base columns in the same row. However, it is not possible to reference other generated columns from within a generation expression.
Note
If the generated expression is deterministic, its value will not be recomputed unless the value of a referenced column has changed.
If values are supplied for generated columns, these values are validated against the result of applying the generation expression:
cr> INSERT INTO computed (dividend, divisor, quotient)
... VALUES (100.0, 2.0, 12.0);
SQLParseException[Given value 12.0 for generated column quotient does not match calculation (dividend / divisor) = 50.0]
Last modified dates¶
Because CURRENT_TIMESTAMP is non-deterministic, you can use this expression to record a last modified date that is set when the row is first inserted, and subsequently updated every time the row is updated:
cr> CREATE TABLE computed_non_deterministic (
... id LONG,
... last_modified TIMESTAMP WITH TIME ZONE GENERATED ALWAYS AS CURRENT_TIMESTAMP
... );
CREATE OK, 1 row affected (... sec)
Partitioning¶
Generated columns can be used with the PARTITIONED BY clause to compute the partition column value from existing columns in the table:
cr> CREATE TABLE computed_and_partitioned (
... huge_cardinality bigint,
... big_data text,
... partition_value GENERATED ALWAYS AS (huge_cardinality % 10)
... ) PARTITIONED BY (partition_value);
CREATE OK, 1 row affected (... sec)