PostgreSQL CREATE VIEW

2021-09-10 14:03 更新

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定義一個查詢的視圖。該視圖不會被 物理上物質(zhì)化。相反,在每一次有查詢引用該視圖時,視圖的查詢都會被運行。

CREATE OR REPLACE VIEW與之相似,但是如果 已經(jīng)存在一個同名視圖,該視圖會被替換。新查詢必須產(chǎn)生和現(xiàn)有試圖查詢相同 的列(也就是相同的列序、相同的列名、相同的數(shù)據(jù)類型),但是它可以在列表 的末尾加上額外的列。產(chǎn)生輸出列的計算可以完全不同。

如果給定了一個模式名(例如CREATE VIEW myschema.myview ...),那么該視圖會被創(chuàng)建在指定的模式中。否則,它會 被創(chuàng)建在當前模式中。臨時視圖存在于一個特殊模式中,因此創(chuàng)建臨時視圖時不能 給定一個模式名。視圖的名稱不能與同一模式中任何其他視圖、表、序列、索引或 外部表同名。

參數(shù)

TEMPORARY或者TEMP

如果被指定,視圖被創(chuàng)建為一個臨時視圖。在當前會話結(jié)束時會自動 刪掉臨時視圖。當臨時視圖存在時,具有相同名稱的已有永久視圖對 當前會話不可見,除非用模式限定的名稱引用它們。

如果視圖引用的任何表是臨時的,視圖將被創(chuàng)建為臨時視圖(不管有 沒有指定TEMPORARY)。

RECURSIVE

創(chuàng)建一個遞歸視圖。語法

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

要創(chuàng)建的視圖的名字(可以是模式限定的)。

column_name

要用于視圖列的名稱列表,可選。如果沒有給出,列名會根據(jù)查詢 推導。

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

這個子句為視圖指定一些可選的參數(shù),支持下列參數(shù):

check_option (enum)

這個參數(shù)可以是local或者cascaded,并且它 等效于指定 WITH [ CASCADED | LOCAL ] CHECK OPTION(見下文)。 可以使用ALTER VIEW在一個現(xiàn)有視圖上修改這個選項。

security_barrier (boolean)

如果希望視圖提供行級安全性,應(yīng)該使用這個參數(shù)。詳見 第 40.5 節(jié)。

query

提供視圖的行和列的一個SELECT或者 VALUES命令。

WITH [ CASCADED | LOCAL ] CHECK OPTION

這個選項控制自動可更新視圖的行為。這個選項被指定時,將檢查該視圖上的 INSERTUPDATE命令以確保新行滿足 視圖的定義條件(也就是,將檢查新行來確保通過視圖能看到它們)。如果新行 不滿足條件,更新將被拒絕。如果沒有指定CHECK OPTION, 會允許該視圖上的INSERTUPDATE命令 創(chuàng)建通過該視圖不可見的行。支持下列檢查選項:

CHECK OPTION不應(yīng)該和RECURSIVE視圖一起使用。

注意,只有在自動可更新的、沒有INSTEAD OF觸發(fā)器或者 INSTEAD規(guī)則的視圖上才支持CHECK OPTION。 如果一個自動可更新的視圖被定義在一個具有INSTEAD OF 觸發(fā)器的基視圖之上,那么LOCAL CHECK OPTION可以被 用來檢查該自動可更新的視圖之上的條件,但具有INSTEAD OF 觸發(fā)器的基視圖上的條件不會被檢查(一個級聯(lián)檢查選項將不會級聯(lián)到一個 觸發(fā)器可更新的視圖,并且任何直接定義在一個觸發(fā)器可更新視圖上的檢查 選項將被忽略)。如果該視圖或者任何基礎(chǔ)關(guān)系具有導致 INSERTUPDATE命令被重寫的 INSTEAD規(guī)則,那么在被重寫的查詢中將忽略所有檢查選項, 包括任何來自于定義在帶有INSTEAD規(guī)則的關(guān)系之上的自動 可更新視圖的檢查。

注解

使用DROP VIEW語句刪除視圖。

要小心視圖列的名稱和類型將會按照你想要的方式指定。例如:

CREATE VIEW vista AS SELECT 'Hello World';

是不好的形式,因為列名默認為?column?,而且列的數(shù)據(jù)類型默認為text,這可能不是用戶想要的。視圖結(jié)果中一個字符串更好的風格類似于這樣:

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

對視圖中引用的表的訪問由視圖擁有者的權(quán)限決定。在某些情況下,這可以 被用來提供安全但是受限的底層表訪問。不過,并非所有視圖都對篡改是安 全的,詳見第 40.5 節(jié)。在視圖中調(diào)用的函數(shù)會被 同樣對待,就好像是直接在使用該視圖的查詢中調(diào)用它們一樣。因此,一個 視圖的用戶必須具有調(diào)用視圖所使用的全部函數(shù)的權(quán)限。

CREATE OR REPLACE VIEW被用在一個現(xiàn)有視圖上時, 只有該視圖的定義 SELECT 規(guī)則被改變。其他包括擁有關(guān)系、權(quán)限和非 SELECT 規(guī)則在內(nèi)的視圖屬性不會被更改。要替換視圖,你必須擁有它(包括 作為擁有角色的一個成員)。

可更新視圖

簡單視圖是自動可更新的:系統(tǒng)將允許在這類視圖上以在常規(guī)表上相同的方式 使用INSERTUPDATE以及 DELETE語句。如果一個視圖滿足以下條件,它就是自動 可更新的:

  • 在該視圖的FROM列表中剛好只有一項,并且它必須是一個 表或者另一個可更新視圖。

  • 視圖定義的頂層不能包含WITHDISTINCT、 GROUP BYHAVING、 LIMIT或者OFFSET子句。

  • 視圖定義的頂層不能包含集合操作(UNION、 INTERSECT或者EXCEPT)。

  • 視圖的選擇列表不能包含任何聚集、窗口函數(shù)或者集合返回函數(shù)。

一個自動可更新的視圖可以混合可更新列以及不可更新列。如果一個列是對底層 基本關(guān)系中一個可更新列的簡單引用,則它是可更新的。否則該列是只讀的,并 且在一個INSERT或者UPDATE語句嘗試對 它賦值時會報出一個錯誤。

如果視圖是自動可更新的,系統(tǒng)將把視圖上的任何INSERT、 UPDATE或者DELETE語句轉(zhuǎn)換成在底層 基本關(guān)系上的對應(yīng)語句。帶有ON CONFLICT UPDATE子句的 INSERT語句已經(jīng)被完全支持。

如果一個自動可更新視圖包含一個WHERE條件,該條件會限制 基本關(guān)系的哪些行可以被該視圖上的UPDATE以及 DELETE語句修改。不過,一個允許被UPDATE 修改的行可能讓該行不再滿足WHERE條件,并且因此也不再能 從視圖中可見。類似地,一個INSERT命令可能插入不滿足 WHERE條件的基本關(guān)系行,并且因此從視圖中也看不到這些行 (ON CONFLICT UPDATE可能會類似地影響無法通過該視圖見 到的現(xiàn)有行)。 CHECK OPTION可以被用來阻止INSERTUPDATE命令創(chuàng)建這類從視圖中無法看到的行。

如果一個自動可更新視圖被標記了security_barrier屬性,那么 所有該屬性的WHERE條件(以及任何使用標記為 LEAKPROOF的操作符的條件)將在該視圖使用者的任何條件 之前計算。詳見第 40.5 節(jié)。注意正因為這樣,不會 被最終返回的行(因為它們不會通過用戶的WHERE條件)可能 仍會結(jié)束被鎖定的狀態(tài)??梢杂?code class="command">EXPLAIN來查看 哪些條件被應(yīng)用在關(guān)系層面(并且因此不鎖定行)以及哪些不會被應(yīng)用在關(guān)系 層面。

一個更加復雜的不滿足所有這些條件的視圖默認是只讀的:系統(tǒng)將不允許在 該視圖上的插入、更新或者刪除??梢酝ㄟ^在該視圖上創(chuàng)建一個 INSTEAD OF觸發(fā)器來獲得可更新視圖的效果,該觸發(fā)器必須 把該視圖上的嘗試的插入等轉(zhuǎn)換成其他表上合適的動作。更多信息請見CREATE TRIGGER。另一種可能性是創(chuàng)建規(guī)則(見 CREATE RULE ),不過實際中觸發(fā)器更容易理解和正確使用。

注意在視圖上執(zhí)行插入、更新或刪除的用戶必須具有該視圖上相應(yīng)的插入、 更新或刪除特權(quán)。此外,視圖的擁有者必須擁有底層基本關(guān)系上的相關(guān)特權(quán), 但是執(zhí)行更新的用戶并不需要底層基本關(guān)系上的任何權(quán)限(見 第 40.5 節(jié))。

示例

創(chuàng)建一個由所有喜劇電影組成的視圖:

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

創(chuàng)建的視圖包含創(chuàng)建時film表中的列。盡管* 被用來創(chuàng)建該視圖,后來被加入到該表中的列不會成為該視圖的組成部分。

創(chuàng)建帶有LOCAL CHECK OPTION的視圖:

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

這將創(chuàng)建一個基于comedies視圖的視圖,只顯示 kind = 'Comedy'classification = 'U'的電影。 如果新行沒有classification = 'U',在該視圖中的任何 INSERTUPDATE嘗試將被拒絕, 但是電影的kind將不會被檢查。

CASCADED CHECK OPTION創(chuàng)建一個視圖:

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

這將創(chuàng)建一個檢查新行的kindclassification 的視圖。

創(chuàng)建一個由可更新列和不可更新列混合而成的視圖:

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表的列都 將是可更新的,而計算列countryavg_rating 將是只讀的。

創(chuàng)建一個由數(shù)字 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中盡管遞歸的視圖名稱是方案限定的,但它內(nèi)部的自引用不是方案限定的。這是因為隱式創(chuàng)建的CTE的名稱不能是方案限定的。

兼容性

CREATE OR REPLACE VIEW是一種 PostgreSQL的語言擴展。臨時 視圖的概念也是這樣。WITH ( ... )子句也是一種擴展。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號