@@ -233,6 +233,124 @@ CREATE TABLE products (
233233 </para>
234234 </sect1>
235235
236+ <sect1 id="ddl-generated-columns">
237+ <title>Generated Columns</title>
238+
239+ <indexterm zone="ddl-generated-columns">
240+ <primary>generated column</primary>
241+ </indexterm>
242+
243+ <para>
244+ A generated column is a special column that is always computed from other
245+ columns. Thus, it is for columns what a view is for tables. There are two
246+ kinds of generated columns: stored and virtual. A stored generated column
247+ is computed when it is written (inserted or updated) and occupies storage
248+ as if it were a normal column. A virtual generated column occupies no
249+ storage and is computed when it is read. Thus, a virtual generated column
250+ is similar to a view and a stored generated column is similar to a
251+ materialized view (except that it is always updated automatically).
252+ PostgreSQL currently implements only stored generated columns.
253+ </para>
254+
255+ <para>
256+ To create a generated column, use the <literal>GENERATED ALWAYS
257+ AS</literal> clause in <command>CREATE TABLE</command>, for example:
258+ <programlisting>
259+ CREATE TABLE people (
260+ ...,
261+ height_cm numeric,
262+ height_in numeric <emphasis>GENERATED ALWAYS AS (height_cm * 2.54) STORED</emphasis>
263+ );
264+ </programlisting>
265+ The keyword <literal>STORED</literal> must be specified to choose the
266+ stored kind of generated column. See <xref linkend="sql-createtable"/> for
267+ more details.
268+ </para>
269+
270+ <para>
271+ A generated column cannot be written to directly. In
272+ <command>INSERT</command> or <command>UPDATE</command> commands, a value
273+ cannot be specified for a generated column, but the keyword
274+ <literal>DEFAULT</literal> may be specified.
275+ </para>
276+
277+ <para>
278+ Consider the differences between a column with a default and a generated
279+ column. The column default is evaluated once when the row is first
280+ inserted if no other value was provided; a generated column is updated
281+ whenever the row changes and cannot be overridden. A column default may
282+ not refer to other columns of the table; a generation expression would
283+ normally do so. A column default can use volatile functions, for example
284+ <literal>random()</literal> or functions referring to the current time;
285+ this is not allowed for generated columns.
286+ </para>
287+
288+ <para>
289+ Several restrictions apply to the definition of generated columns and
290+ tables involving generated columns:
291+
292+ <itemizedlist>
293+ <listitem>
294+ <para>
295+ The generation expression can only use immutable functions and cannot
296+ use subqueries or reference anything other than the current row in any
297+ way.
298+ </para>
299+ </listitem>
300+ <listitem>
301+ <para>
302+ A generation expression cannot reference another generated column.
303+ </para>
304+ </listitem>
305+ <listitem>
306+ <para>
307+ A generation expression cannot reference a system column, except
308+ <varname>tableoid</varname>.
309+ </para>
310+ </listitem>
311+ <listitem>
312+ <para>
313+ A generated column cannot have a column default or an identity definition.
314+ </para>
315+ </listitem>
316+ <listitem>
317+ <para>
318+ A generated column cannot be part of a partition key.
319+ </para>
320+ </listitem>
321+ <listitem>
322+ <para>
323+ Foreign tables can have generated columns. See <xref
324+ linkend="sql-createforeigntable"/> for details.
325+ </para>
326+ </listitem>
327+ </itemizedlist>
328+ </para>
329+
330+ <para>
331+ Additional considerations apply to the use of generated columns.
332+ <itemizedlist>
333+ <listitem>
334+ <para>
335+ Generated columns maintain access privileges separately from their
336+ underlying base columns. So, it is possible to arrange it so that a
337+ particular role can read from a generated column but not from the
338+ underlying base columns.
339+ </para>
340+ </listitem>
341+ <listitem>
342+ <para>
343+ Generated columns are, conceptually, updated after
344+ <literal>BEFORE</literal> triggers have run. Therefore, changes made to
345+ base columns in a <literal>BEFORE</literal> trigger will be reflected in
346+ generated columns. But conversely, it is not allowed to access
347+ generated columns in <literal>BEFORE</literal> triggers.
348+ </para>
349+ </listitem>
350+ </itemizedlist>
351+ </para>
352+ </sect1>
353+
236354 <sect1 id="ddl-constraints">
237355 <title>Constraints</title>
238356
0 commit comments