CREATE VIEW — 定義一個新檢視
CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] VIEWname
[ (column_name
[, ...] ) ] [ WITH (view_option_name
[=view_option_value
] [, ... ] ) ] ASquery
[ WITH [ CASCADED | LOCAL ] CHECK OPTION ]
CREATE VIEW
定義一個查詢的檢視。該檢視不會被物理地具體化。相反,每次在查詢中引用檢視時,都會執行該查詢。
CREATE OR REPLACE VIEW
類似,但如果同名的檢視已存在,則會被替換。新的查詢必須生成與現有檢視查詢相同的列(即,相同名稱、相同順序和相同資料型別的列),但可以向列表末尾新增額外的列。產生輸出列的計算可以完全不同。
如果給出了模式名(例如 CREATE VIEW myschema.myview ...
),則檢視將在指定的模式中建立。否則,它將在當前模式中建立。臨時檢視存在於一個特殊的模式中,因此在建立臨時檢視時不能給出模式名。檢視的名稱必須與同一模式中任何其他關係(表、序列、索引、檢視、具體化檢視或外部表)的名稱不同。
TEMPORARY
或 TEMP
如果指定,檢視將被建立為臨時檢視。臨時檢視將在當前會話結束時自動刪除。當臨時檢視存在時,具有相同名稱的現有永久關係在本會話中不可見,除非使用模式限定的名稱引用它們。
如果檢視引用的任何表是臨時的,則檢視將被建立為臨時檢視(無論是否指定了 TEMPORARY
)。
RECURSIVE
建立遞迴檢視。語法
CREATE RECURSIVE VIEW [schema
. ]view_name
(column_names
) AS SELECT...
;
等同於
CREATE VIEW [schema
. ]view_name
AS WITH RECURSIVEview_name
(column_names
) AS (SELECT...
) SELECTcolumn_names
FROMview_name
;
對於遞迴檢視,必須指定檢視列名列表。
name
要建立的檢視的名稱(可選模式限定)。
column_name
可選的名稱列表,用於檢視的列。如果未給出,則列名將從查詢中推斷出來。
WITH ( view_option_name
[= view_option_value
] [, ... ] )
此子句指定檢視的可選引數;支援以下引數
check_option
(enum
)此引數可以是 local
或 cascaded
,等同於指定 WITH [ CASCADED | LOCAL ] CHECK OPTION
(見下文)。
security_barrier
(boolean
)如果檢視旨在提供行級安全,則應使用此選項。有關完整詳細資訊,請參閱第 39.5 節。
security_invoker
(boolean
)此選項導致底層基表根據檢視使用者的許可權進行檢查,而不是檢視所有者的許可權。有關詳細資訊,請參閱下面的註釋。
可以使用 ALTER VIEW
更改上述所有選項的現有檢視。
query
WITH [ CASCADED | LOCAL ] CHECK OPTION
此選項控制自動可更新檢視的行為。指定此選項時,將檢查對檢視的 INSERT
、UPDATE
和 MERGE
命令,以確保新行滿足檢視定義條件(即,檢查新行以確保它們可以透過檢視可見)。如果它們不可見,則更新將被拒絕。如果未指定 CHECK OPTION
,則允許對檢視執行 INSERT
、UPDATE
和 MERGE
命令,建立不可透過檢視可見的行。支援以下檢查選項:
LOCAL
新行僅根據檢視本身直接定義的條件進行檢查。底層基檢視上定義的任何條件都不會被檢查(除非它們也指定了 CHECK OPTION
)。
CASCADED
新行將根據檢視以及所有底層基檢視的條件進行檢查。如果指定了 CHECK OPTION
,並且未指定 LOCAL
或 CASCADED
,則假定為 CASCADED
。
CHECK OPTION
不能與 RECURSIVE
檢視一起使用。
請注意,CHECK OPTION
僅支援自動可更新的檢視,並且不具有 INSTEAD OF
觸發器或 INSTEAD
規則。如果自動可更新檢視是基於具有 INSTEAD OF
觸發器的基檢視定義的,則可以使用 LOCAL CHECK OPTION
來檢查自動可更新檢視上的條件,但不會檢查具有 INSTEAD OF
觸發器的基檢視上的條件(級聯檢查選項不會級聯到可觸發更新的檢視,直接在可觸發更新的檢視上定義的任何檢查選項都將被忽略)。如果檢視或其任何基關係具有導致 INSERT
或 UPDATE
命令重寫的 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 規則,將保持不變。您必須擁有檢視才能替換它(這包括成為所有者角色的成員)。
簡單檢視是自動可更新的:系統將允許在檢視上使用 INSERT
、UPDATE
、DELETE
和 MERGE
語句,就像在常規表上一樣。如果檢視滿足以下所有條件,則它是自動可更新的:
檢視在其 FROM
子句中必須只有一項,並且該項必須是表或另一個可更新檢視。
檢視定義在頂層不得包含 WITH
、DISTINCT
、GROUP BY
、HAVING
、LIMIT
或 OFFSET
子句。
檢視定義在頂層不得包含集合運算(UNION
、INTERSECT
或 EXCEPT
)。
檢視的 SELECT 列表不得包含任何聚合函式、視窗函式或集合返回函式。
自動可更新的檢視可能包含可更新和不可更新列的混合。如果列是對底層基關係的可更新列的簡單引用,則該列是可更新的;否則,該列是隻讀的,如果 INSERT
、UPDATE
或 MERGE
語句嘗試為其賦值,則會引發錯誤。
如果檢視是自動可更新的,系統會將檢視上的任何 INSERT
、UPDATE
、DELETE
或 MERGE
語句轉換為底層基關係上的相應語句。INSERT
語句具有 ON CONFLICT UPDATE
子句將得到完全支援。
如果自動可更新檢視包含 WHERE
條件,該條件會限制基關係中可以透過檢視的 UPDATE
、DELETE
和 MERGE
語句修改的行。但是,允許 UPDATE
或 MERGE
更改一個行,使其不再滿足 WHERE
條件,從而不再透過檢視可見。類似地,INSERT
或 MERGE
命令可能插入不滿足 WHERE
條件的基關係行,從而不可透過檢視可見(ON CONFLICT UPDATE
也可能影響一個不可透過檢視可見的現有行)。CHECK OPTION
可用於防止 INSERT
、UPDATE
和 MERGE
命令建立此類不可透過檢視可見的行。
如果自動可更新檢視被標記為 security_barrier
屬性,則檢視的所有 WHERE
條件(以及使用標記為 LEAKPROOF
的運算子的任何條件)將始終在任何使用者新增的條件之前進行評估。有關詳細資訊,請參閱第 39.5 節。請注意,因此,最終未返回的行(因為它們未能透過使用者的 WHERE
條件)可能仍會被鎖定。EXPLAIN
可用於檢視哪些條件在關係級別應用(因此不鎖定行),哪些不是。
不滿足所有這些條件的更復雜的檢視預設是隻讀的:系統不允許在檢視上執行 INSERT
、UPDATE
、DELETE
或 MERGE
。可以透過在檢視上建立 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'
的電影。任何嘗試在檢視中 INSERT
或 UPDATE
行的操作,如果新行不具有 classification = 'U'
,將被拒絕,但電影 kind
不會進行檢查。
建立帶有 CASCADED CHECK OPTION
的檢視
CREATE VIEW pg_comedies AS SELECT * FROM comedies WHERE classification = 'PG' WITH CASCADED CHECK OPTION;
這將建立一個檢查新行的 kind
和 classification
的檢視。
建立包含可更新和不可更新列混合的檢視
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';
此檢視將支援 INSERT
、UPDATE
和 DELETE
。來自 films
表的所有列都是可更新的,而計算出的列 country
和 avg_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 VIEW
是 PostgreSQL 語言的擴充套件。臨時檢視的概念也是如此。WITH ( ... )
子句也是擴充套件,安全屏障檢視和安全呼叫者檢視也是如此。
如果您在文件中看到任何不正確、與您在該特定功能上的經驗不符或需要進一步闡明的內容,請使用此表單報告文件問題。