↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 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 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

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 ( ... )子句同样是扩展。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。