Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

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 对现有视图更改所有上述选项。

查询

将提供视图的列和行的 SELECTVALUES 命令。

WITH [ CASCADED | LOCAL ] CHECK OPTION

此选项控制自动更新视图的行为。指定此选项后,视图上的 INSERTUPDATEMERGE 命令将会得到检查,以确保新行满足视图定义条件(即检查新行以确保其通过视图可见)。如果不满足条件,则会拒绝更新。如果未指定 CHECK OPTION,则视图上的 INSERTUPDATEMERGE 命令能够创建并非通过视图可见的行。支持下列检查选项

LOCAL

仅根据视图本身直接定义的条件对新行执行检查。对基础基本视图定义的任何条件都不进行检查(除非它们还指定了 CHECK OPTION)。

CASCADED

根据视图以及所有基础基本视图的条件对新行进行检查。如果指定了 CHECK OPTION,且既未指定 LOCAL,也未指定 CASCADED,那么系统将假定为 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)。

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

可自动更新的视图可能包含可更新列和不可更新列的混合。如果列是基础基本关系的可更新列的简单引用,则该列可更新;否则该列为只读,如果 INSERTUPDATEMERGE 语句尝试向其分配值,将会引发错误。

如果视图可自动更新,则系统将在视图上转换任何 INSERTUPDATEDELETEMERGE 语句,将其转换为基本基本关系上的相应语句。完全支持带 ON CONFLICT UPDATE 子句的 INSERT 语句。

如果可自动更新的视图包含 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' 的电影。如果新行不具有 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';

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

另请参阅

ALTER VIEWDROP VIEWCREATE MATERIALIZED VIEW