选择 打开 改范围 完整检索页
受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10
当前 PostgreSQL 版本不在支持生命周期内。
您可以参阅当前版本的对应页面,或其他在上面列出的活跃大版本。

CREATE VIEW

CREATE VIEW — 定义一个新视图

Synopsis

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(见下文)。可以使用ALTER VIEW更改现有视图上的此选项。

security_barrier (boolean)

如果视图旨在提供行级安全,则应使用此选项。完整细节请参见Section 40.5

query

一个将为该视图提供列和行的SELECTVALUES命令。

WITH [ CASCADED | LOCAL ] CHECK OPTION

该选项控制自动可更新视图的行为。指定该选项时,INSERTUPDATE这些命令在视图上执行时,会检查新行是否满足视图定义的条件(也就是说,会检查新行是否可通过该视图看到)。如果不满足,更新将被拒绝。如果CHECK OPTION未指定,INSERTUPDATE这些命令可以在视图上创建通过该视图不可见的行。支持以下检查选项:

LOCAL

新行只会根据该视图自身直接定义的条件进行检查。底层基视图上定义 的任何条件都不会被检查(除非它们也指定了 CHECK OPTION)。

CASCADED

新行会根据该视图及所有底层基视图的条件进行检查。如果指定了 CHECK OPTION,但既未指定 LOCAL也未指定CASCADED, 则假定为CASCADED

CHECK OPTION不能与RECURSIVE视图一起使用。

注意,CHECK OPTION仅支持自动可更新且不带INSTEAD OF触发器或INSTEAD规则的视图。如果一个自动可更新视图定义在带有INSTEAD OF触发器的基视图之上,则可以使用LOCAL CHECK OPTION检查该自动可更新视图的条件,但不会检查带有INSTEAD OF触发器的基视图上的条件(级联检查选项不会继续向下级联到触发器可更新视图,而直接定义在触发器可更新视图上的任何检查选项也会被忽略)。如果该视图或其任何基关系带有会导致INSERTUPDATE命令被重写的INSTEAD规则,则在重写后的查询中所有检查选项都会被忽略,包括来自定义在带有INSTEAD规则的关系之上的自动可更新视图的任何检查选项。

注解

使用DROP VIEW语句删除视图。

应留意视图列的名称和类型是否按预期确定。例如:

CREATE VIEW vista AS SELECT 'Hello World';

这种写法不好,因为列名默认是?column?;而且列数据 类型默认是text,这可能并非所需。若要在视图结果中使 用字符串字面量,更好的写法类似于:

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

对视图中引用的表的访问由视图所有者的权限决定。在某些情况下,这可以用于为底层表提供安全但受限的访问。不过,并非所有视图都能防止篡改;详情请参见Section 40.5。视图调用的函数与直接从使用该视图的查询中调用时的处理方式相同。因此,视图的用户必须拥有调用视图所用全部函数的权限。

对现有视图使用CREATE OR REPLACE VIEW时,只会更改视图的定义性 SELECT 规则。其他视图属性(包括所有权、权限和非 SELECT 规则)保持不变。必须拥有该视图才能替换它(包括作为所有者角色的成员)。

可更新视图

简单视图是自动可更新的:系统允许INSERTUPDATE以及DELETE语句以与普通表相同的方式用于该视图。满足以下所有条件的视图是自动可更新的:

  • 该视图的FROM列表中必须恰好只有一项,而且这一 项必须是一个表或另一个可更新视图。

  • 视图定义的顶层不能包含WITHDISTINCTGROUP BYHAVINGLIMIT或者OFFSET子句。

  • 视图定义的顶层不能包含集合操作(UNIONINTERSECT或者EXCEPT)。

  • 视图的 SELECT 列表不能包含任何聚合函数、窗口函数或集合返回函数。

自动可更新视图可以同时包含可更新列和不可更新列。如果某列只是简单引用了底层基关系中的一个可更新列,则该列是可更新的;否则,该列为只读,如果INSERTUPDATE语句试图为其赋值,就会报错。

如果视图是自动可更新的,系统会把视图上的任何INSERTUPDATEDELETE语句转换为底层基关系上的对应语句。带有ON CONFLICT UPDATE子句的INSERT语句也得到完全支持。

如果自动可更新视图包含WHERE条件,那么在该视图上执行UPDATEDELETE语句时,该条件会限制底层基关系中哪些行可被修改。不过,UPDATE仍可能把某一行改成不再满足WHERE条件,从而使其不再能通过该视图看到。类似地,INSERT命令也可能插入不满足WHERE条件的基关系行,因此这些行通过该视图不可见(ON CONFLICT UPDATE也可能类似地影响现有的、通过该视图不可见的行)。可以使用CHECK OPTION阻止INSERTUPDATE命令创建这类通过该视图不可见的行。

如果自动可更新视图带有security_barrier属性,那么 视图上的所有WHERE条件(以及任何使用标记为 LEAKPROOF的操作符的条件)总会先于视图使用者添加 的任何条件求值。详见Section 40.5。请注意,因此 那些最终不会返回的行(因为它们未通过用户的WHERE条 件)仍可能被锁定。可以使用EXPLAIN查看哪些条件是 在关系级别应用的(因而不会锁定行),哪些则不是。

默认情况下,不满足所有这些条件的更复杂视图是只读的:系统不允许在该视图上执行插入、更新或删除。可以通过在视图上创建INSTEAD OF触发器来实现可更新视图的效果;这些触发器必须把针对该视图的插入等操作转换为在其他表上执行的适当动作。有关更多信息,请参见CREATE TRIGGER。另一种可能性是创建规则(参见CREATE RULE),但实际上触发器更容易理解和正确使用。

请注意,在视图上执行插入、更新或删除的用户必须拥有该视图上相应的插入、更新或删除权限。此外,视图所有者必须拥有底层基关系上的相关权限,但执行更新的用户不需要拥有底层基关系上的任何权限(参见Section 40.5)。

示例

创建一个包含所有喜剧电影的视图:

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 ( ... )子句同样是扩展,安全屏障视图和安 全调用者视图也是如此。