Skip to content

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 (布尔值)

如果视图旨在提供行级安全性,则应使用此项。有关详细信息,请参阅第 41.5 节

security_invoker (布尔值)

此选项会导致根据视图用户的权限(而非视图所有者的权限)检查基础基本关系。有关详细信息,请参阅以下注释。

使用ALTER VIEW可以在现有视图中更改所有上述选项。

查询

将提供视图的列和行的SELECTVALUES命令。

WITH [ CASCADED | LOCAL ] CHECK OPTION

此选项控制自动可更新视图的行为。指定此选项时,将检查视图上的INSERTUPDATE命令,以确保新行满足视图定义条件(即,检查新行以确保它们通过视图可见)。如果不满足,则将拒绝更新。如果未指定CHECK OPTION,则允许视图上的INSERTUPDATE命令创建通过视图不可见的行。支持以下检查选项

LOCAL

仅根据视图本身中直接定义的条件检查新行。不会检查在基础基本视图上定义的任何条件(除非它们也指定CHECK OPTION)。

CASCADED

根据视图和所有基础基本视图的条件检查新行。如果指定了CHECK OPTION,并且未指定LOCALCASCADED,则假定为CASCADED

不能将CHECK OPTIONRECURSIVE视图一起使用。

请注意,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;

默认情况下,对视图中引用的底层基本关系的访问由视图所有者的权限决定。在某些情况下,这可用于提供对底层表的安全但受限的访问。但是,并非所有视图都能防篡改;有关详细信息,请参阅第 41.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 规则)保持不变。您必须拥有视图才能替换它(包括成为所有者角色的成员)。

可更新视图

简单视图是自动可更新的:系统将允许在视图上使用INSERTUPDATEDELETE语句,就像在普通表上使用一样。如果视图满足以下所有条件,则它是自动可更新的

  • 视图在其 FROM 列表中必须只有一个条目,该条目必须是表或另一个可更新视图。

  • 视图定义不能在顶层包含 WITHDISTINCTGROUP BYHAVINGLIMITOFFSET 子句。

  • 视图定义不能在顶层包含集合运算(UNIONINTERSECTEXCEPT)。

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

自动可更新视图可能包含可更新和不可更新列的混合。如果列是对底层基本关系的可更新列的简单引用,则该列是可更新的;否则,该列是只读的,如果INSERTUPDATE语句尝试向其分配值,则会引发错误。

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

如果自动可更新视图包含WHERE条件,则该条件会限制基本关系的哪些行可以通过视图上的UPDATEDELETE语句进行修改。但是,允许UPDATE更改一行,使其不再满足WHERE条件,因此不再通过视图可见。类似地,INSERT命令可能会插入不满足WHERE条件的基本关系行,因此通过视图不可见(ON CONFLICT UPDATE可能会以类似方式影响通过视图不可见的现有行)。CHECK OPTION可用于防止INSERTUPDATE命令创建此类通过视图不可见的行。

如果自动可更新视图已标记为security_barrier属性,则所有视图的WHERE条件(以及使用标记为LEAKPROOF的运算符的任何条件)都将始终在视图用户添加的任何条件之前进行评估。有关完整详细信息,请参阅第 41.5 节。请注意,由于此原因,最终未返回的行(因为它们未通过用户的WHERE条件)仍可能最终被锁定。EXPLAIN可用于查看哪些条件应用于关系级别(因此不会锁定行),哪些条件不会。

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

请注意,在视图上执行插入、更新或删除的用户必须对该视图拥有相应的插入、更新或删除权限。此外,默认情况下,视图的所有者必须对底层基本关系拥有相关权限,而执行更新的用户不需要对底层基本关系有任何权限(请参阅第 41.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'的电影。如果新行没有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 VIEW是PostgreSQL语言扩展。临时视图的概念也是如此。WITH ( ... )子句也是一个扩展,安全屏障视图和安全调用者视图也是如此。

另请参见

ALTER VIEWDROP VIEWCREATE MATERIALIZED VIEW