afterwards (see
<xref linkend="sql-altertable"/>).
</para>
<para>
An identity column is automatically marked as <literal>NOT NULL</literal>.
An identity column, however, does not guarantee uniqueness. (A sequence
normally returns unique values, but a sequence could be reset, or values
could be inserted manually into the identity column, as discussed above.)
Uniqueness would need to be enforced using a <literal>PRIMARY KEY</literal>
or <literal>UNIQUE</literal> constraint.
</para>
<para>
In table inheritance hierarchies, identity columns and their properties in
a child table are independent of those in its parent tables. A child table
does not inherit identity columns or their properties automatically from
the parent. During <command>INSERT</command> or <command>UPDATE</command>,
a column is treated as an identity column if that column is an identity
column in the table named in the statement, and the corresponding identity
properties are applied.
</para>
<para>
Partitions inherit identity columns from the partitioned table. They
cannot have their own identity columns. The properties of a given identity
column are consistent across all the partitions in the partition hierarchy.
</para>
</sect1>
<sect1 id="ddl-generated-columns">
<title>Generated Columns</title>
<indexterm zone="ddl-generated-columns">
<primary>generated column</primary>
</indexterm>
<para>
A generated column is a special column that is always computed from other
columns. Thus, it is for columns what a view is for tables. There are two
kinds of generated columns: stored and virtual. A stored generated column
is computed when it is written (inserted or updated) and occupies storage
as if it were a normal column. A virtual generated column occupies no
storage and is computed when it is read. Thus, a virtual generated column
is similar to a view and a stored generated column is similar to a
materialized view (except that it is always updated automatically).
</para>
<para>
To create a generated column, use the <literal>GENERATED ALWAYS
AS</literal> clause in <command>CREATE TABLE</command>, for example:
<programlisting>
CREATE TABLE people (
...,
height_cm numeric,
height_in numeric <emphasis>GENERATED ALWAYS AS (height_cm / 2.54)</emphasis>
);
</programlisting>
A generated column is by default of the virtual kind. Use the keywords
<literal>VIRTUAL</literal> or <literal>STORED</literal> to make the choice
explicit. See <xref linkend="sql-createtable"/> for more details.
</para>
<para>
A generated column cannot be written to directly. In
<command>INSERT</command> or <command>UPDATE</command> commands, a value
cannot be specified for a generated column, but the keyword
<literal>DEFAULT</literal> may be specified.
</para>
<para>
Consider the differences between a column with a default and a generated
column. The column default is evaluated once when the row is first
inserted if no other value was provided; a generated column is updated
whenever the row changes and cannot be overridden. A column default may
not refer to other columns of the table; a generation expression would
normally do so. A column default can use volatile functions, for example
<literal>random()</literal> or functions referring to the current time;
this is not allowed for generated columns.
</para>
<para>
Several restrictions apply to the definition of generated columns and
tables involving generated columns:
<itemizedlist>
<listitem>
<para>
The generation expression can only use immutable functions and cannot
use subqueries or reference anything other than the current row in any
way.
</para>
</listitem>
<listitem>
<para>
A generation expression cannot reference another generated column.
</para>
</listitem>
<listitem>
<para>