生成列は常に他の列から計算される特別な列です。 ですから、これは列におけるテーブルに対するビューのようなものです。 生成列には格納と仮想の2種類があります。 格納生成列はそれが書かれた(挿入または更新)時に計算され、あたかも通常の列のようにストレージが割り当てられます。 仮想列にはストレージは割り当てられず、列が読み出された時に計算されます。 つまり、仮想生成列はビューに似ており、格納生成列はマテリアライズドビューに似ています。(常に自動的に更新される点は除きます。) 今の所PostgreSQLは格納生成列のみを実装しています。
生成列を作るには、CREATE TABLE
でGENERATED ALWAYS AS
節を使ってください。例を示します。
CREATE TABLE people (
...,
height_cm numeric,
height_in numeric GENERATED ALWAYS AS (height_cm / 2.54) STORED
);
種類を格納生成列として選択するためにキーワードSTORED
を選択する必要があります。
より詳しくはCREATE TABLEをご覧ください。
生成列には直接書き込みができません。
INSERT
あるいはUPDATE
コマンドでは値を生成列に指定できませんが、キーワードDEFAULT
が指定できます。
デフォルトを備えた列と生成列の違いを考えてみましょう。
列のデフォルトは、他に値が指定されないときに、最初に行が挿入された時に一度だけ評価されます。
生成列は、行が変更された時に常に更新され、上書きはできません。
デフォルトを備えた列はテーブルの他の列を参照することはできませんが、生成式は通常それを行います。
デフォルトを備えた列は揮発性の関数、たとえばrandom()
や現在時刻を参照する関数を使用できますが、これは生成列では許されていません。
生成列の定義と生成列を伴うテーブルには以下の制限が適用されます。
生成式は不変関数のみが使用でき、副問合せ、あるいは現在の行以外へのいかなる参照も使用できません。
生成式はほかの生成列を参照できません。
生成式はtableoid
以外のシステム列を参照できません。
生成列は列デフォルトも識別定義も持てません。
生成列はパーティションキーの一部にはなれません。
外部テーブルは生成列を持つことができます。 詳細はCREATE FOREIGN TABLEをご覧ください。
For inheritance and partitioning:
《機械翻訳》親カラムが生成済カラムである場合、その子カラムも生成済カラムである必要があります。 ただし、子カラムは別の世代式を持つことができます。 行の挿入時または更新時に実際に適用される世代式は、行が物理的に存在する表に関連付けられたものです。 (これはカラムのデフォルトの動作とは異なります。 つまり、クエリの記名的表に関連付けられたデフォルト値が適用されます。)
《機械翻訳》親カラムが生成されたカラムでない場合、その子カラムも生成されてはなりません。
《機械翻訳》継承されたテーブルの場合、CREATEカラム.定義
にGENERATED
句を持たない子テーブル継承を書き込むと、そのGENERATED
句は自動的に親からコピーされます。
ALTERテーブル.INHERIT
は、親と子カラムが世代ステータスに関してすでにマッチであることを要求しますが、マッチへの世代式は必要ありません。
《機械翻訳》テーブルパーティションの場合と同様に、CREATEカラム.定義OF
にGENERATED
句を持たない子テーブルパーティションを記述すると、そのGENERATED
句は自動的に親からコピーされます。
ALTERテーブル.アタッチパーティション
は、親列と子列が世代ステータスに関してマッチであることを主張しますが、マッチに対してそれらの世代式を要求しません。
《マッチ度[54.117647]》多重継承では、一つの親列が生成列なら、すべての親列は同じ式による生成列でなければなりません。 《機械翻訳》複数の継承の場合、1つの親列が生成された列である場合、すべての親列は生成された列である必要があります。 それらのすべてが同じ世代式を持っていない場合、子の目的の式を明示的に指定する必要があります。
《機械翻訳》マルチプル継承のケースでは、1つの親カラムが生成されたカラムである場合、すべての親列を生成列にする必要があります。 すべての式に同じ世代の式がない場合は、子に対して目的のを明示的に指定する必要があります。
生成列の利用の際には以下の追加の考慮が必要です。
生成列は元になる基底列とは別にアクセス権限を維持します。 ですから、ある特定のロールが生成列を読み出しつつも、元になる基底列からは読み出さないように調整できます。
概念的には、生成列はBEFORE
トリガが走った後に更新されます。
ですから、BEFORE
トリガの中で基底列に加えられた変更は生成列に反映されます。
しかし逆に生成列をBEFORE
トリガの中でアクセスすることは許されません。