2024 年 9 月 26 日: PostgreSQL 17 发布!
支持版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持的版本: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 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 BYHAVINGLIMITOFFSET子句在顶层。

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

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

自动可更新视图可能包含可更新列和不可更新列的混合。如果列是对底层基本关系的可更新列的简单引用,则该列是可更新的;否则该列是只读的,如果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';

此视图将支持INSERTUPDATEDELETEfilms表中的所有列都是可更新的,而计算列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 ( ... )子句也是扩展,安全屏障视图和安全调用者视图也是如此。

提交更正

如果您在文档中看到任何不正确的内容,与您对特定功能的体验不符或需要进一步说明,请使用此表格报告文档问题。