9.3 9.4 9.5 9.6 10 11 12 13 14 Current(15)
阿里云PostgreSQL 问题报告 纠错本页面

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

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

security_barrier (boolean)

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

security_invoker (boolean)

此选项导致基础基本关系根据视图用户的权限而不是视图所有者的权限进行检查。详细信息请参见下文的注释。

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

query

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

WITH [ CASCADED | LOCAL ] CHECK OPTION

这个选项控制自动可更新视图的行为。这个选项被指定时,将检查该视图上的 INSERTUPDATE命令以确保新行满足 视图的定义条件(也就是,将检查新行来确保通过视图能看到它们)。如果新行 不满足条件,更新将被拒绝。如果没有指定CHECK OPTION, 会允许该视图上的INSERTUPDATE命令 创建通过该视图不可见的行。支持下列检查选项:

LOCAL

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

CASCADED

会根据该视图和所有底层基视图上的条件检查新行。如果 CHECK OPTION被指定,并且没有指定 LOCALCASCADED,则会假定为 CASCADED

CHECK OPTION不应该和RECURSIVE视图一起使用。

注意,只有在自动可更新的、没有INSTEAD OF触发器或者 INSTEAD规则的视图上才支持CHECK OPTION。 如果一个自动可更新的视图被定义在一个具有INSTEAD OF 触发器的基视图之上,那么LOCAL CHECK OPTION可以被 用来检查该自动可更新的视图之上的条件,但具有INSTEAD OF 触发器的基视图上的条件不会被检查(一个级联检查选项将不会级联到一个 触发器可更新的视图,并且任何直接定义在一个触发器可更新视图上的检查 选项将被忽略)。如果该视图或者任何基础关系具有导致 INSERTUPDATE命令被重写的 INSTEAD规则,那么在被重写的查询中将忽略所有检查选项, 包括任何来自于定义在带有INSTEAD规则的关系之上的自动 可更新视图的检查。

注解

使用DROP VIEW语句删除视图。

要小心视图列的名称和类型将会按照你想要的方式指定。例如:

CREATE VIEW vista AS SELECT 'Hello World';

是不好的形式,因为列名默认为?column?,而且列的数据类型默认为text,这可能不是用户想要的。视图结果中一个字符串更好的风格类似于这样:

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

默认情况下,对视图中引用的基础关系的访问权限由视图所有者的权限确定。在某些情况下, 这可以用来提供对基础表的安全但受限制的访问。然而,并非所有视图都能防止篡改;详见 第 41.5 节

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

如果任何基础关系中有一个是安全调用者视图,它将被视为直接从原始查询中访问。 因此,安全调用者视图将始终使用当前用户的权限检查其基础关系,即使它是从没有 security_invoker属性的视图中访问。

如果任何基础关系中有启用行级安全,那么默认情况下,视图所有者的行级安全策略将被应用, 并且对于这些策略引用的任何其他关系的访问将由视图所有者的权限确定。然而,如果视图设置了security_invokertrue, 那么调用用户的策略和权限将被使用,就好像基础关系直接从查询中使用视图引用一样。

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

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

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

可更新视图

简单视图是自动可更新的:系统将允许在这类视图上以在常规表上相同的方式 使用INSERTUPDATE以及 DELETE语句。如果一个视图满足以下条件,它就是自动 可更新的:

  • 在该视图的FROM列表中刚好只有一项,并且它必须是一个 表或者另一个可更新视图。

  • 视图定义的顶层不能包含WITHDISTINCTGROUP BYHAVINGLIMIT或者OFFSET子句。

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

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

一个自动可更新的视图可以混合可更新列以及不可更新列。如果一个列是对底层 基本关系中一个可更新列的简单引用,则它是可更新的。否则该列是只读的,并 且在一个INSERT或者UPDATE语句尝试对 它赋值时会报出一个错误。

如果视图是自动可更新的,系统将把视图上的任何INSERTUPDATE或者DELETE语句转换成在底层 基本关系上的对应语句。带有ON CONFLICT UPDATE子句的 INSERT语句已经被完全支持。

如果一个自动可更新视图包含一个WHERE条件,该条件会限制 基本关系的哪些行可以被该视图上的UPDATE以及 DELETE语句修改。不过,一个允许被UPDATE 修改的行可能让该行不再满足WHERE条件,并且因此也不再能 从视图中可见。类似地,一个INSERT命令可能插入不满足 WHERE条件的基本关系行,并且因此从视图中也看不到这些行 (ON CONFLICT UPDATE可能会类似地影响无法通过该视图见 到的现有行)。 CHECK OPTION可以被用来阻止INSERTUPDATE命令创建这类从视图中无法看到的行。

如果一个自动可更新视图被标记了security_barrier属性,那么 所有该属性的WHERE条件(以及任何使用标记为 LEAKPROOF的操作符的条件)将在该视图使用者的任何条件 之前计算。详见第 41.5 节。注意正因为这样,不会 被最终返回的行(因为它们不会通过用户的WHERE条件)可能 仍会结束被锁定的状态。可以用EXPLAIN来查看 哪些条件被应用在关系层面(并且因此不锁定行)以及哪些不会被应用在关系 层面。

一个更加复杂的不满足所有这些条件的视图默认是只读的:系统将不允许在 该视图上的插入、更新或者删除。可以通过在该视图上创建一个 INSTEAD OF触发器来获得可更新视图的效果,该触发器必须 把该视图上的尝试的插入等转换成其他表上合适的动作。更多信息请见CREATE TRIGGER。另一种可能性是创建规则(见 CREATE RULE),不过实际中触发器更容易理解和正确使用。

注意,执行对视图进行插入、更新或删除操作的用户必须对该视图具有相应的插入、更新或删除权限。 另外,默认情况下,视图的所有者必须对底层基本关系具有相关权限,而执行更新操作的用户不需要对底层基本关系有任何权限 (参见第 41.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'的电影。 如果新行没有classification = 'U',在该视图中的任何 INSERTUPDATE尝试将被拒绝, 但是电影的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';

这个视图将支持INSERTUPDATE 以及DELETE。所有来自于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 VIEW是一个PostgreSQL语言扩展。 临时视图的概念也是如此。 WITH ( ... )子句也是一个扩展,安全屏障视图和安全调用者视图也是如此。

另见

ALTER VIEW, DROP VIEW, CREATE MATERIALIZED VIEW