2025年9月25日: PostgreSQL 18 釋出!
支援版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援版本: 12

5.4. 生成列 #

生成列是一種特殊的列,它總是根據其他列計算得來。因此,它對於列的作用類似於檢視對於表的作用。生成列有兩種型別:儲存型和虛擬型。儲存型生成列在寫入時(插入或更新)計算,並佔用儲存空間,就像普通列一樣。虛擬型生成列不佔用儲存空間,在讀取時計算。因此,虛擬型生成列類似於檢視,而儲存型生成列類似於物化檢視(只是它總是自動更新)。

要建立生成列,請在 CREATE TABLE 中使用 GENERATED ALWAYS AS 子句,例如:

CREATE TABLE people (
    ...,
    height_cm numeric,
    height_in numeric GENERATED ALWAYS AS (height_cm / 2.54)
);

生成列預設是虛擬型別。使用 VIRTUALSTORED 關鍵字可以明確選擇。有關更多詳細資訊,請參閱 CREATE TABLE

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

請注意列的預設值和生成列之間的區別。列的預設值在插入行時僅評估一次(如果未提供其他值);生成列在行發生更改時更新,並且不能被覆蓋。列的預設值不能引用表中的其他列;而生成表示式通常會這樣做。列的預設值可以使用易變函式(volatile functions),例如 random() 或引用當前時間的函式;這不允許用於生成列。

生成列以及包含生成列的表的定義有幾個限制:

  • 生成表示式只能使用不可變函式(immutable functions),不能使用子查詢,也不能以任何方式引用當前行之外的內容。

  • 生成表示式不能引用另一個生成列。

  • 生成表示式不能引用系統列,但 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 INVOKERSECURITY DEFINER,以執行查詢的使用者或函式所有者的許可權來執行。

  • 生成列的概念上是在 BEFORE 觸發器執行之後更新的。因此,在 BEFORE 觸發器中對基列所做的更改將反映在生成列中。但反之,不允許在 BEFORE 觸發器中訪問生成列。

  • 根據 CREATE PUBLICATION 引數 publish_generated_columns 或透過將它們包含在 CREATE PUBLICATION 命令的列列表中,允許在邏輯複製期間複製生成列。目前這僅支援儲存型生成列。有關詳細資訊,請參閱 第 29.6 節

提交更正

如果您在文件中發現任何不正確、與您對特定功能的使用體驗不符或需要進一步說明的內容,請使用 此表單 報告文件問題。