受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

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(见下文)。

security_barrier (boolean) #

如果该视图旨在提供行级安全,则应使用此选项。详见 Section 39.5

security_invoker (boolean) #

该选项会根据视图使用者而非视图所有者的权限来检查底层基关系。 完整细节见下文注解。

以上所有选项都可以通过ALTER VIEW 在现有视图上修改。

query #

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

WITH [ CASCADED | LOCAL ] CHECK OPTION #

该选项控制自动可更新视图的行为。指定该选项时,会检查对该视图执行的 INSERTUPDATEMERGE 命令,以确保新行满足视图定义条件(即确保能够通过该视图看到这些新 行)。如果不满足条件,该修改将被拒绝。若未指定 CHECK OPTION,则允许在该视图上执行 INSERTUPDATEMERGE 命令来创建通过该视图不可见的行。支持以下检查选项:

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规则的关系之上的自动可更新视图的任何检 查。若该视图或其任何基关系带有规则,则不支持 MERGE

注解

使用DROP VIEW语句删除视图。

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

CREATE VIEW vista AS SELECT 'Hello World';

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

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

默认情况下,访问视图中引用的底层基关系时,会依据视图所有者的权限进 行判断。在某些情况下,这可用于为底层表提供安全但受限的访问。然而, 并非所有视图都能防止被篡改;详见Section 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权限,而不需要对视 图查询中引用的模式拥有该权限,即使对于安全调用者视图也是如此。

当对现有视图使用CREATE OR REPLACE VIEW时,只会更 改视图定义的SELECT规则,以及任何 WITH ( ... )参数和其CHECK OPTION。 其他视图属性,包括所有权、权限和非SELECT规则,都 保持不变。要替换该视图,你必须拥有它(这也包括成为拥有该视图的角色 的成员)。

可更新视图

简单视图是自动可更新的:系统允许像对普通表一样在视图上使用 INSERTUPDATEDELETEMERGE语句。满足下列所 有条件的视图是自动可更新的:

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

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

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

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

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

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

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

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

默认情况下,更复杂且不满足上述全部条件的视图是只读的:系统不允许对 该视图执行INSERTUPDATEDELETEMERGE。可以通过在该视 图上创建INSTEAD OF触发器来获得可更新视图的效果, 这类触发器必须把针对该视图的插入等操作转换为在其他表上执行的适当动 作。更多信息请见CREATE TRIGGER。另一种可能性是 创建规则(见CREATE RULE),但在实践中,触发器 更容易理解和正确使用。另外请注意,带有规则的关系不支持 MERGE

注意,在视图上执行插入、更新或删除的用户,必须拥有该视图上相应的插 入、更新或删除权限。另外,默认情况下,视图所有者必须在底层基关系上 拥有相关权限,而执行更新的用户则不需要在底层基关系上拥有任何权限 (参见Section 39.5)。但是,如果视图的 security_invoker设置为true,则 必须由执行更新的用户而非视图所有者,在底层基关系上拥有相关权限。

示例

创建一个由所有喜剧影片组成的视图:

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

这会创建一个视图,其中包含创建视图时films表中的各 列。尽管创建视图时使用了*,但以后添加到该表的列 不会成为该视图的一部分。

创建带有LOCAL CHECK OPTION的视图:

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

这会创建一个基于视图comedies的视图,只显示 kind = 'Comedy'classification = 'U'的影片。如果新行不满足 classification = 'U',则任何对该视图执行 INSERTUPDATE的尝试都会被拒 绝,但不会检查影片的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 ( ... )子句同样是扩展,安全屏障视图和安 全调用者视图也是如此。

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。