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

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

百科 / SQL 命令 / 表与视图

SQL COMMAND · 表与视图

CREATE VIEW

定义一个新视图

CREATE表与视图引入 10(基线)现存至 20 devel0 次语法变更

动词
CREATE
对象
VIEW
引入版本
10(基线)
状态
现存
语法变更次数
0
手册小节数
6

本站手册 · 18官方文档 ↗

版本轨迹

相对 PostgreSQL 17 无变化。

语法铁道图 PostgreSQL 18

沿轨道从左向右阅读,分岔表示选择,绕行表示可选,回环表示重复。方框为参数,点击带下划线的参数可展开子规则。

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 [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] VIEW name [ ( column_name [, ...] ) ]
    [ WITH ( view_option_name [= view_option_value] [, ... ] ) ]
    AS query
    [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]

PostgreSQL 18 手册 · 查看完整参考页

描述

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

此参数可以是local或cascaded,等同于指定 WITH [ CASCADED | LOCAL ] CHECK OPTION(见下文)。

security_barrier (boolean)

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

security_invoker (boolean)

该选项会根据视图使用者而非视图所有者的权限来检查底层基关系。完整细节见下文注解。

以上所有选项都可以通过ALTER VIEW 在现有视图上修改。

query

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

WITH [ CASCADED | LOCAL ] CHECK OPTION

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

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规则的关系之上的自动可更新视图的任何检查。若该视图或其任何基关系带有规则,则不支持 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规则,都保持不变。要替换该视图,你必须拥有它(这也包括成为拥有该视图的角色的成员)。

可更新视图

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

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

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

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

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

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

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

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

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

默认情况下,更复杂且不满足上述全部条件的视图是只读的:系统不允许对该视图执行INSERT、UPDATE、DELETE或MERGE。可以通过在该视图上创建INSTEAD OF触发器来获得可更新视图的效果,这类触发器必须把针对该视图的插入等操作转换为在其他表上执行的适当动作。更多信息请见CREATE TRIGGER。另一种可能性是创建规则(见CREATE RULE),但在实践中,触发器更容易理解和正确使用。另外请注意,带有规则的关系不支持 MERGE。

注意,在视图上执行插入、更新或删除的用户,必须拥有该视图上相应的插入、更新或删除权限。另外,默认情况下,视图所有者必须在底层基关系上拥有相关权限,而执行更新的用户则不需要在底层基关系上拥有任何权限(参见第 39.5 节)。但是,如果视图的 security_invoker设置为true,则必须由执行更新的用户而非视图所有者,在底层基关系上拥有相关权限。

示例

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

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 ( ... )子句同样是扩展,安全屏障视图和安全调用者视图也是如此。

另见

语法演化

相邻大版本之间的差异,新的在前。版本号链接到对应快照。

  1. PostgreSQL 20← 19正文更新

    正文更新
  2. PostgreSQL 19← 18正文更新

    正文更新
  3. PostgreSQL 17← 16正文更新

    正文更新
  4. PostgreSQL 15← 14正文更新

    正文更新
  5. PostgreSQL 14← 13正文更新

    正文更新
  6. PostgreSQL 13← 12正文更新

    正文更新
  7. PostgreSQL 12← 11正文更新

    正文更新
  8. PostgreSQL 11← 10正文更新

    正文更新

同组命令

命令动词对象版本变动最近变更
TABLES & VIEWS表与视图15 条↑
TRUNCATETRUNCATE— —
清空一个表或一组表现存
CREATE MATERIALIZED VIEWCREATEMATERIALIZED VIEW 121 次
定义一个新物化视图现存
ALTER MATERIALIZED VIEWALTERMATERIALIZED VIEW 164 次
更改一个物化视图的定义现存
DROP MATERIALIZED VIEWDROPMATERIALIZED VIEW —
移除一个物化视图现存
REFRESH MATERIALIZED VIEWREFRESHMATERIALIZED VIEW —
替换物化视图的内容现存
CREATE SEQUENCECREATESEQUENCE 182 次
定义一个新的序列发生器现存
ALTER SEQUENCEALTERSEQUENCE 183 次
更改序列发生器的定义现存
DROP SEQUENCEDROPSEQUENCE —
移除一个序列现存
CREATE TABLECREATETABLE 198 次
定义一个新表现存
ALTER TABLEALTERTABLE 188 次
更改一个表的定义现存
DROP TABLEDROPTABLE —
移除一个表现存
CREATE TABLE ASCREATETABLE AS 192 次
根据查询结果定义一个新表现存
CREATE VIEWCREATEVIEW —
定义一个新视图现存
ALTER VIEWALTERVIEW 142 次
更改视图的定义现存
DROP VIEWDROPVIEW —
移除一个视图现存