生成列は常に他の列から計算される特別な列です。 ですから、これは列におけるテーブルに対するビューのようなものです。 生成列には格納生成列と仮想生成列の2種類があります。 格納生成列はそれが書かれた(挿入または更新)時に計算され、あたかも通常の列のようにストレージが割り当てられます。 仮想生成列にはストレージは割り当てられず、列が読み出された時に計算されます。 つまり、仮想生成列はビューに似ており、格納生成列はマテリアライズドビューに似ています(常に自動的に更新される点は除きます)。
生成列を作るには、CREATE TABLEでGENERATED ALWAYS AS句を使ってください。例を示します。
CREATE TABLE people (
...,
height_cm numeric,
height_in numeric GENERATED ALWAYS AS (height_cm / 2.54)
);
生成列はデフォルトでは仮想生成列となります。
明示的に選択するためには、キーワードVIRTUALまたはSTOREDを使用してください。
詳細はCREATE TABLEを参照してください。
生成列には直接書き込みができません。
INSERTあるいはUPDATEコマンドでは値を生成列に指定できませんが、キーワードDEFAULTが指定できます。
デフォルトを備えた列と生成列の違いを考えてみましょう。
列のデフォルトは、他に値が指定されないときに、最初に行が挿入された時に一度だけ評価されます。
生成列は、行が変更された時に常に更新され、上書きはできません。
デフォルトを備えた列はテーブルの他の列を参照することはできませんが、生成式は通常それを行います。
デフォルトを備えた列は揮発性の関数、たとえばrandom()や現在時刻を参照する関数を使用できますが、これは生成列では許されていません。
生成列の定義と生成列を伴うテーブルには以下の制限が適用されます。
生成式は不変関数のみが使用でき、副問い合わせ、あるいは現在の行以外へのいかなる参照も使用できません。
生成式はほかの生成列を参照できません。
生成式はtableoid以外のシステム列を参照できません。
仮想生成列にはユーザ定義型を使用できず、仮想生成列の生成式はユーザ定義の関数または型を参照してはいけません。 つまり、組み込みの関数または型のみ使用できます。 これは、演算子やキャストの基礎となる関数や型などにも間接的に当てはまります。 (この制限は、格納生成列には存在しません。)
生成列は列デフォルトも識別定義も持てません。
生成列はパーティションキーの一部にはなれません。
外部テーブルは生成列を持つことができます。 詳細はCREATE FOREIGN TABLEをご覧ください。
継承とパーティショニングの場合:
親列が生成列である場合、その子列も同じ種類(格納または仮想)の生成列でなければなりません。 しかし、子列は異なる生成式を持つことができます。
格納生成列の場合、行の挿入または更新時に実際に適用される生成式は、物理的に行が存在するテーブルに関連付けられたものです。 (これは列デフォルトの動作とは異なります。 列デフォルトの場合、問い合わせで指定されたテーブルに関連付けられたデフォルト値が適用されます。) 仮想生成列の場合、テーブルが読まれるときに、問い合わせで指定されたテーブルの生成式が適用されます。
親列が生成列でない場合、その子列も生成列であってはなりません。
継承されたテーブルの場合、CREATE TABLE ... INHERITSにGENERATED句を持たない子テーブル継承を書き込むと、そのGENERATED句は自動的に親からコピーされます。
ALTER TABLE ... INHERITは、親列と子列が生成状態に一致していることを要求しますが、それらの生成式が一致することを要求しません。
パーティション化されたテーブルの場合も同様です。
CREATE TABLE ... PARTITION OFにGENERATED句を持たない子テーブル継承を書き込むと、そのGENERATED句は自動的に親からコピーされます。
ALTER TABLE ... ATTACH PARTITIONは、親列と子列が生成状態に一致していることを要求しますが、それらの生成式が一致することを要求しません。
多重継承では、一つの親列が生成列なら、すべての親列は生成列でなければなりません。 すべての親列が同じ生成式を持たない場合は、子列の望ましい式を明示的に指定する必要があります。
生成列の利用の際には以下の追加の考慮が必要です。
生成列は元になる基底列とは別にアクセス権限を維持します。 ですから、ある特定のロールが生成列を読み出しつつも、元になる基底列からは読み出さないように調整できます。
仮想生成列の場合、生成式が漏洩防止(leakproof)関数(CREATE FUNCTIONを参照)だけを使用する場合にのみ完全に安全ですが、システムによって強制されるわけではありません。
生成式で使用される関数の権限は、書き込み時または読み取り時それぞれで、式が実際に実行されるときに確認されます。
これは、あたかも生成列を使用する問い合わせから生成式が直接呼び出されたかのように行われます。
生成列のユーザは、生成式で使用されるすべての関数を呼び出す権限を持っている必要があります。
生成式内の関数は、関数がSECURITY INVOKERまたはSECURITY DEFINERとして定義されているかどうかに応じて、問い合わせを実行するユーザの権限または関数所有者の権限で実行されます。
概念的には、生成列はBEFOREトリガが走った後に更新されます。
ですから、BEFOREトリガの中で基底列に加えられた変更は生成列に反映されます。
しかし逆に生成列をBEFOREトリガの中でアクセスすることは許されません。
生成列は、CREATE PUBLICATIONのパラメータpublish_generated_columnsに従って、またはCREATE PUBLICATIONコマンドの列リストにそれらを含めることで、論理レプリケーション中に複製できます。
これは現在、格納生成列でのみサポートされています。
詳細は29.6を参照してください。