支持的版本: 当前 (17) / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

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 (boolean)

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

security_invoker (boolean)

此选项使底层基本关系根据视图用户的权限而不是视图所有者的权限进行检查。有关详细信息,请参阅下面的说明。

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

query

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

WITH [ CASCADED | LOCAL ] CHECK OPTION

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

LOCAL

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

CASCADED

根据视图的所有条件和所有底层基本视图检查新行。如果指定了CHECK OPTION,并且没有指定LOCALCASCADED,则假定为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;

默认情况下,对视图中引用的底层基本关系的访问由视图所有者的权限确定。在某些情况下,这可以用于提供对底层表的安全但受限的访问。但是,并非所有视图都能安全地防止篡改;有关详细信息,请参阅第 39.5 节

如果视图的security_invoker属性设置为true,则对底层基本关系的访问由执行查询的用户的权限而不是视图所有者的权限确定。因此,安全调用者视图的用户必须具有对视图及其底层基本关系的相关权限。

如果任何底层基本关系是安全调用者视图,则会将其视为已从原始查询中直接访问。因此,即使从不具有security_invoker属性的视图访问,安全调用者视图也始终会使用当前用户的权限检查其底层基本关系。

如果任何底层基本关系启用了行级安全性,则默认情况下,将应用视图所有者的行级安全性策略,并且对这些策略引用的任何其他关系的访问由视图所有者的权限确定。但是,如果视图的security_invoker设置为true,则会使用调用用户的策略和权限,就好像直接从使用该视图的查询中引用了基本关系一样。

在视图中调用的函数将以与直接从使用该视图的查询中调用它们相同的方式处理。因此,视图的用户必须具有调用视图使用的所有函数的权限。视图中的函数以执行查询的用户或函数所有者的权限执行,具体取决于这些函数是否定义为SECURITY INVOKERSECURITY DEFINER。因此,例如,直接在视图中调用CURRENT_USER将始终返回调用用户,而不是视图所有者。这不受视图的security_invoker设置的影响,因此将security_invoker设置为false的视图等效于SECURITY DEFINER函数,并且不应混淆这些概念。

创建或替换视图的用户必须对视图查询中引用的任何模式具有 USAGE 权限,以便查找这些模式中引用的对象。但请注意,此查找仅在创建或替换视图时发生。因此,视图的用户只需要对包含视图的模式具有 USAGE 权限,而不需要对视图查询中引用的模式具有 USAGE 权限,即使是安全调用者视图也是如此。

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

可更新视图

简单视图会自动可更新:系统将允许在视图上使用 INSERTUPDATEDELETEMERGE 语句,其方式与在普通表上使用相同。如果视图满足以下所有条件,则该视图会自动可更新

  • 视图的 FROM 列表中必须恰好有一个条目,该条目必须是一个表或另一个可更新的视图。

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

  • 视图定义在顶层不能包含集合操作符(UNIONINTERSECTEXCEPT)。

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

一个自动可更新的视图可能包含可更新和不可更新的列的混合。如果一列是底层基本关系的可更新列的简单引用,则该列是可更新的;否则,该列是只读的,并且如果 INSERTUPDATEMERGE 语句尝试为其赋值,则会引发错误。

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

如果自动可更新的视图包含 WHERE 条件,则该条件会限制可以通过视图上的 UPDATEDELETEMERGE 语句修改的基础关系的行。但是,允许 UPDATEMERGE 更改一行,使其不再满足 WHERE 条件,从而不再通过视图可见。类似地,INSERTMERGE 命令可能会插入不满足 WHERE 条件的基础关系行,因此这些行不会通过视图可见(ON CONFLICT UPDATE 可能也会影响通过视图不可见的现有行)。可以使用 CHECK OPTION 来防止 INSERTUPDATEMERGE 命令创建此类通过视图不可见的行。

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

默认情况下,不满足所有这些条件的更复杂的视图是只读的:系统将不允许在视图上执行 INSERTUPDATEDELETEMERGE。您可以通过在视图上创建 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' 的电影。如果在视图中 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 ( ... ) 子句也是一个扩展,安全屏障视图和安全调用者视图也是如此。

提交更正

如果您在文档中发现任何不正确的内容、与特定功能的体验不符或需要进一步澄清的地方,请使用此表格报告文档问题。