支援的版本: 最新 (17) / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12

5.4. 產生欄位 (Generated Columns) #

產生欄位是一種特殊的欄位,它總是從其他欄位計算而來。因此,對於欄位而言,它就像視窗對於表格一樣。有兩種產生欄位:儲存的和虛擬的。儲存的產生欄位在寫入(插入或更新)時計算,並像普通欄位一樣佔用儲存空間。虛擬的產生欄位不佔用儲存空間,並在讀取時計算。因此,虛擬產生欄位類似於視窗,而儲存的產生欄位類似於具體化視窗(只是它始終自動更新)。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

產生欄位不能直接寫入。在 INSERTUPDATE 命令中,不能為產生欄位指定值,但可以指定關鍵字 DEFAULT

考慮具有預設值的欄位和產生欄位之間的差異。如果未提供其他值,則在首次插入列時,欄位預設值會計算一次;產生欄位會在列每次變更時更新,並且無法覆寫。欄位預設值可能不會參照表格的其他欄位;而產生運算式通常會這樣做。欄位預設值可以使用不穩定的函式,例如 random() 或參照目前時間的函式;產生欄位不允許這樣做。

以下限制適用於產生欄位和包含產生欄位的表格的定義

  • 產生運算式只能使用不可變的函式,並且不能使用子查詢或以任何方式參照目前列以外的任何內容。

  • 產生運算式不能參照另一個產生欄位。

  • 產生運算式不能參照系統欄位,除了 tableoid

  • 產生欄位不能具有欄位預設值或身分定義。

  • 產生欄位不能是分割索引鍵的一部分。

  • 外部表格可以具有產生欄位。有關詳細資訊,請參閱 CREATE FOREIGN TABLE

  • 對於繼承和分割

    • 如果父欄位是產生欄位,則其子欄位也必須是產生欄位;但是,子欄位可以具有不同的產生運算式。在插入或更新列期間實際套用的產生運算式是與列實際所在的表格相關聯的運算式。(這與欄位預設值的行為不同:對於這些值,套用與查詢中命名的表格相關聯的預設值。)

    • 如果父欄位不是產生欄位,則其子欄位也不得產生。

    • 對於繼承的表格,如果您在 CREATE TABLE ... INHERITS 中編寫沒有任何 GENERATED 子句的子欄位定義,則其 GENERATED 子句將自動從父欄位複製。ALTER TABLE ... INHERIT 將堅持父欄位和子欄位在產生狀態方面已經匹配,但它不會要求它們的產生運算式匹配。

    • 對於分割表格也是如此,如果您在 CREATE TABLE ... PARTITION OF 中編寫沒有任何 GENERATED 子句的子欄位定義,則其 GENERATED 子句將自動從父欄位複製。ALTER TABLE ... ATTACH PARTITION 將堅持父欄位和子欄位在產生狀態方面已經匹配,但它不會要求它們的產生運算式匹配。

    • 在多重繼承的情況下,如果一個父欄位是產生欄位,則所有父欄位都必須是產生欄位。如果它們並非都具有相同的產生運算式,則必須明確指定子欄位的所需運算式。

其他考量適用於產生欄位的使用。

  • 產生欄位維護與其基礎基本欄位不同的存取權限。因此,可以安排使特定角色可以從產生欄位讀取,但不能從基礎基本欄位讀取。

  • 從概念上講,產生欄位會在 BEFORE 觸發程序執行後更新。因此,在 BEFORE 觸發程序中對基本欄位所做的變更將反映在產生欄位中。但相反,不允許在 BEFORE 觸發程序中存取產生欄位。

  • 產生欄位會跳過邏輯複寫,並且不能在 CREATE PUBLICATION 欄位清單中指定。

提交更正

如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步澄清的地方,請使用此表格回報文件問題。