↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 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 / 7.0 / 6.5 / 6.4
历史版本。 PostgreSQL 12 已结束支持。 2024-11-21. 请参阅 当前版本手册.

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 ...),则视图将在指定的模式中创建。否则,它将在当前模式中创建。临时视图存在于一个特殊模式中,因此在创建临时视图时不能给出模式名称。视图的名称必须与同一模式中的任何其他视图、表、序列、索引或外部表的名称不同。

参数

TEMPORARY 或 TEMP

如果指定该选项,视图将被创建为临时视图。临时视图会在当前会话结束时自动删除。当临时视图存在时,除非使用模式限定名称引用,否则具有相同名称的现有永久关系对当前会话不可见。

如果视图引用的任何表是临时表,则该视图也会被创建为临时视图(无论是否指定了 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 (string)

该参数可以是 local 或 cascaded,等同于指定 WITH [ CASCADED | LOCAL ] CHECK OPTION(见下文)。可以使用 ALTER VIEW 更改现有视图上的此选项。

security_barrier (boolean)

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

query

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

WITH [ CASCADED | LOCAL ] CHECK OPTION

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

LOCAL

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

CASCADED

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

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

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

注解

使用 DROP VIEW 语句删除视图。

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

CREATE VIEW vista AS SELECT 'Hello World';

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

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

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

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

可更新视图

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

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

  • 视图定义的顶层不能包含 WITH、DISTINCT、GROUP BY、HAVING、LIMIT 或者 OFFSET 子句。

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

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

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

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

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

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

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

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

示例

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

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',则任何对该视图执行 INSERT 或 UPDATE 的尝试都会被拒绝,但不会检查影片的 kind。

创建带有 CASCADED CHECK OPTION 的视图:

CREATE VIEW pg_comedies AS
    SELECT *
    FROM comedies
    WHERE classification = 'PG'
    WITH CASCADED CHECK OPTION;

这会创建一个同时检查新行 kind 和 classification 的视图。

创建一个同时包含可更新列和不可更新列的视图:

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';

该视图将支持 INSERT、UPDATE 和 DELETE。所有来自 films 表的列都可更新,而计算列 country 和 avg_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 ( ... ) 子句同样是扩展。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.