2025年9月25日: PostgreSQL 18 釋出!
支援的版本:當前18) / 17 / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

CREATE VIEW

CREATE VIEW — 定義一個新檢視

概要

CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] VIEW name [ ( column_name [, ...] ) ]
    [ WITH ( view_option_name [= view_option_value] [, ... ] ) ]
    AS query
    [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]

描述

CREATE VIEW 定義一個查詢的檢視。該檢視不會被物理地具體化。相反,每次在查詢中引用檢視時,都會執行該查詢。

CREATE OR REPLACE VIEW 類似,但如果同名的檢視已存在,則會被替換。新的查詢必須生成與現有檢視查詢相同的列(即,相同名稱、相同順序和相同資料型別的列),但可以向列表末尾新增額外的列。產生輸出列的計算可以完全不同。

如果給出了模式名(例如 CREATE VIEW myschema.myview ...),則檢視將在指定的模式中建立。否則,它將在當前模式中建立。臨時檢視存在於一個特殊的模式中,因此在建立臨時檢視時不能給出模式名。檢視的名稱必須與同一模式中任何其他關係(表、序列、索引、檢視、具體化檢視或外部表)的名稱不同。

引數

TEMPORARYTEMP

如果指定,檢視將被建立為臨時檢視。臨時檢視將在當前會話結束時自動刪除。當臨時檢視存在時,具有相同名稱的現有永久關係在本會話中不可見,除非使用模式限定的名稱引用它們。

如果檢視引用的任何表是臨時的,則檢視將被建立為臨時檢視(無論是否指定了 TEMPORARY)。

RECURSIVE

建立遞迴檢視。語法

CREATE RECURSIVE VIEW [ schema . ] view_name (column_names) AS SELECT ...;

等同於

CREATE VIEW [ schema . ] view_name AS WITH RECURSIVE view_name (column_names) AS (SELECT ...) SELECT column_names FROM view_name;

對於遞迴檢視,必須指定檢視列名列表。

name

要建立的檢視的名稱(可選模式限定)。

column_name

可選的名稱列表,用於檢視的列。如果未給出,則列名將從查詢中推斷出來。

WITH ( view_option_name [= view_option_value] [, ... ] )

此子句指定檢視的可選引數;支援以下引數

check_option (enum)

此引數可以是 localcascaded,等同於指定 WITH [ CASCADED | LOCAL ] CHECK OPTION(見下文)。

security_barrier (boolean)

如果檢視旨在提供行級安全,則應使用此選項。有關完整詳細資訊,請參閱第 39.5 節

security_invoker (boolean)

此選項導致底層基表根據檢視使用者的許可權進行檢查,而不是檢視所有者的許可權。有關詳細資訊,請參閱下面的註釋。

可以使用 ALTER VIEW 更改上述所有選項的現有檢視。

query

一個 SELECTVALUES 命令,它將提供檢視的列和行。

WITH [ CASCADED | LOCAL ] CHECK OPTION

此選項控制自動可更新檢視的行為。指定此選項時,將檢查對檢視的 INSERTUPDATEMERGE 命令,以確保新行滿足檢視定義條件(即,檢查新行以確保它們可以透過檢視可見)。如果它們不可見,則更新將被拒絕。如果未指定 CHECK OPTION,則允許對檢視執行 INSERTUPDATEMERGE 命令,建立不可透過檢視可見的行。支援以下檢查選項:

LOCAL

新行僅根據檢視本身直接定義的條件進行檢查。底層基檢視上定義的任何條件都不會被檢查(除非它們也指定了 CHECK OPTION)。

CASCADED

新行將根據檢視以及所有底層基檢視的條件進行檢查。如果指定了 CHECK OPTION,並且未指定 LOCALCASCADED,則假定為 CASCADED

CHECK OPTION 不能與 RECURSIVE 檢視一起使用。

請注意,CHECK OPTION 僅支援自動可更新的檢視,並且不具有 INSTEAD OF 觸發器或 INSTEAD 規則。如果自動可更新檢視是基於具有 INSTEAD OF 觸發器的基檢視定義的,則可以使用 LOCAL CHECK OPTION 來檢查自動可更新檢視上的條件,但不會檢查具有 INSTEAD OF 觸發器的基檢視上的條件(級聯檢查選項不會級聯到可觸發更新的檢視,直接在可觸發更新的檢視上定義的任何檢查選項都將被忽略)。如果檢視或其任何基關係具有導致 INSERTUPDATE 命令重寫的 INSTEAD 規則,則在重寫的查詢中將忽略所有檢查選項,包括來自在該具有 INSTEAD 規則的關係之上定義的自動可更新檢視的任何檢查。如果檢視或其任何基關係具有規則,則不支援 MERGE

註釋

使用 DROP VIEW 語句刪除檢視。

請小心,確保檢視列的名稱和型別按您預期的方式分配。例如

CREATE VIEW vista AS SELECT 'Hello World';

是不好的做法,因為列名預設為 ?column?;此外,列資料型別預設為 text,這可能不是您想要的。對於檢視結果中的字串文字,更好的風格是類似以下內容:

CREATE VIEW vista AS SELECT text 'Hello World' AS hello;

預設情況下,對檢視中引用的底層基關係的訪問由檢視所有者的許可權決定。在某些情況下,這可以用於提供安全但受限的對底層表的訪問。但是,並非所有檢視都能夠防篡改;有關詳細資訊,請參閱第 39.5 節

如果檢視的 security_invoker 屬性設定為 true,則對底層基關係的訪問由執行查詢的使用者的許可權決定,而不是檢視所有者的許可權。因此,安全呼叫者檢視的使用者必須在檢視及其底層基關係上擁有相關許可權。

如果任何底層基關係是安全呼叫者檢視,它將被視為直接從原始查詢訪問。因此,即使安全呼叫者檢視被一個沒有 security_invoker 屬性的檢視訪問,它也會使用當前使用者的許可權檢查其底層基關係。

如果任何底層基關係啟用了行級安全,則預設情況下,將應用檢視所有者的行級安全策略,並且對這些策略引用的任何其他關係的訪問由檢視所有者的許可權決定。但是,如果檢視的 security_invoker 設定為 true,則將使用呼叫者的策略和許可權,就好像基關係是從使用該檢視的查詢中直接引用的一樣。

在檢視中呼叫的函式與直接從使用該檢視的查詢中呼叫的函式具有相同的待遇。因此,檢視使用者必須擁有呼叫檢視使用的所有函式的許可權。檢視中的函式將使用執行查詢的使用者或函式所有者的許可權來執行,具體取決於函式是定義為 SECURITY INVOKER 還是 SECURITY DEFINER。因此,例如,直接在檢視中呼叫 CURRENT_USER 將始終返回呼叫者,而不是檢視所有者。這不受檢視的 security_invoker 設定的影響,因此 security_invoker 設定為 false 的檢視與 SECURITY DEFINER 函式不完全等同,不應混淆這些概念。

建立或替換檢視的使用者必須對檢視查詢中引用的任何模式擁有 USAGE 許可權,以便在這些模式中查詢引用的物件。但請注意,此查詢僅在建立或替換檢視時發生。因此,檢視的使用者只需要對包含檢視的模式具有 USAGE 許可權,而不必對檢視查詢中引用的模式具有 USAGE 許可權,即使是對於安全呼叫者檢視。

當對現有檢視使用 CREATE OR REPLACE VIEW 時,只有檢視定義的 SELECT 規則以及任何 WITH ( ... ) 引數及其 CHECK OPTION 會被更改。其他檢視屬性,包括所有權、許可權和非 SELECT 規則,將保持不變。您必須擁有檢視才能替換它(這包括成為所有者角色的成員)。

可更新檢視

簡單檢視是自動可更新的:系統將允許在檢視上使用 INSERTUPDATEDELETEMERGE 語句,就像在常規表上一樣。如果檢視滿足以下所有條件,則它是自動可更新的:

  • 檢視在其 FROM 子句中必須只有一項,並且該項必須是表或另一個可更新檢視。

  • 檢視定義在頂層不得包含 WITHDISTINCTGROUP BYHAVINGLIMITOFFSET 子句。

  • 檢視定義在頂層不得包含集合運算(UNIONINTERSECTEXCEPT)。

  • 檢視的 SELECT 列表不得包含任何聚合函式、視窗函式或集合返回函式。

自動可更新的檢視可能包含可更新和不可更新列的混合。如果列是對底層基關係的可更新列的簡單引用,則該列是可更新的;否則,該列是隻讀的,如果 INSERTUPDATEMERGE 語句嘗試為其賦值,則會引發錯誤。

如果檢視是自動可更新的,系統會將檢視上的任何 INSERTUPDATEDELETEMERGE 語句轉換為底層基關係上的相應語句。INSERT 語句具有 ON CONFLICT UPDATE 子句將得到完全支援。

如果自動可更新檢視包含 WHERE 條件,該條件會限制基關係中可以透過檢視的 UPDATEDELETEMERGE 語句修改的行。但是,允許 UPDATEMERGE 更改一個行,使其不再滿足 WHERE 條件,從而不再透過檢視可見。類似地,INSERTMERGE 命令可能插入不滿足 WHERE 條件的基關係行,從而不可透過檢視可見(ON CONFLICT UPDATE 也可能影響一個不可透過檢視可見的現有行)。CHECK OPTION 可用於防止 INSERTUPDATEMERGE 命令建立此類不可透過檢視可見的行。

如果自動可更新檢視被標記為 security_barrier 屬性,則檢視的所有 WHERE 條件(以及使用標記為 LEAKPROOF 的運算子的任何條件)將始終在任何使用者新增的條件之前進行評估。有關詳細資訊,請參閱第 39.5 節。請注意,因此,最終未返回的行(因為它們未能透過使用者的 WHERE 條件)可能仍會被鎖定。EXPLAIN 可用於檢視哪些條件在關係級別應用(因此不鎖定行),哪些不是。

不滿足所有這些條件的更復雜的檢視預設是隻讀的:系統不允許在檢視上執行 INSERTUPDATEDELETEMERGE。可以透過在檢視上建立 INSTEAD OF 觸發器來獲得可更新檢視的效果,這些觸發器必須將嘗試在檢視上執行的插入等操作轉換為在其他表上執行的適當操作。有關更多資訊,請參閱CREATE TRIGGER。另一種可能性是建立規則(請參閱CREATE RULE),但實際上觸發器更容易理解和正確使用。另請注意,規則關係不支援 MERGE

請注意,執行檢視上的插入、更新或刪除的使用者必須擁有檢視上的相應插入、更新或刪除許可權。此外,預設情況下,檢視的所有者必須在底層基關係上擁有相關許可權,而執行更新的使用者不需要在底層基關係上擁有任何許可權(請參閱第 39.5 節)。但是,如果檢視的 security_invoker 設定為 true,則執行更新的使用者而不是檢視所有者必須在底層基關係上擁有相關許可權。

示例

建立一個包含所有喜劇電影的檢視

CREATE VIEW comedies AS
    SELECT *
    FROM films
    WHERE kind = 'Comedy';

這將建立一個包含檢視建立時 film 表中存在的列的檢視。儘管建立檢視時使用了 *,但稍後新增到表中的列將不屬於檢視。

建立帶有 LOCAL CHECK OPTION 的檢視

CREATE VIEW universal_comedies AS
    SELECT *
    FROM comedies
    WHERE classification = 'U'
    WITH LOCAL CHECK OPTION;

這將建立一個基於 comedies 檢視的檢視,僅顯示 kind = 'Comedy'classification = 'U' 的電影。任何嘗試在檢視中 INSERTUPDATE 行的操作,如果新行不具有 classification = 'U',將被拒絕,但電影 kind 不會進行檢查。

建立帶有 CASCADED CHECK OPTION 的檢視

CREATE VIEW pg_comedies AS
    SELECT *
    FROM comedies
    WHERE classification = 'PG'
    WITH CASCADED CHECK OPTION;

這將建立一個檢查新行的 kindclassification 的檢視。

建立包含可更新和不可更新列混合的檢視

CREATE VIEW comedies AS
    SELECT f.*,
           country_code_to_name(f.country_code) AS country,
           (SELECT avg(r.rating)
            FROM user_ratings r
            WHERE r.film_id = f.id) AS avg_rating
    FROM films f
    WHERE f.kind = 'Comedy';

此檢視將支援 INSERTUPDATEDELETE。來自 films 表的所有列都是可更新的,而計算出的列 countryavg_rating 將是隻讀的。

建立一個由 1 到 100 的數字組成的遞迴檢視

CREATE RECURSIVE VIEW public.nums_1_100 (n) AS
    VALUES (1)
UNION ALL
    SELECT n+1 FROM nums_1_100 WHERE n < 100;

請注意,儘管在此 CREATE 中遞迴檢視的名稱是模式限定的,但其內部自我引用不是模式限定的。這是因為隱式建立的 CTE 的名稱不能被模式限定。

相容性

CREATE OR REPLACE VIEWPostgreSQL 語言的擴充套件。臨時檢視的概念也是如此。WITH ( ... ) 子句也是擴充套件,安全屏障檢視和安全呼叫者檢視也是如此。

提交更正

如果您在文件中看到任何不正確、與您在該特定功能上的經驗不符或需要進一步闡明的內容,請使用此表單報告文件問題。