CREATE VIEW — 定义一个新视图
CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] VIEWname[ (column_name[, ...] ) ] [ WITH (view_option_name[=view_option_value] [, ... ] ) ] ASquery[ 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_nameAS WITH RECURSIVEview_name(column_names) AS (SELECT...) SELECTcolumn_namesFROMview_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 更改上述所有选项的现有视图。
queryWITH [ 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 权限,而不必对视图查询中引用的模式具有 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 语句转换为底层基关系上的相应语句。INSERT 语句具有 ON CONFLICT UPDATE 子句将得到完全支持。
如果自动可更新视图包含 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';
这将创建一个包含视图创建时 film 表中存在的列的视图。尽管创建视图时使用了 *,但稍后添加到表中的列将不属于视图。
创建带有 LOCAL CHECK OPTION 的视图
CREATE VIEW universal_comedies AS
SELECT *
FROM comedies
WHERE classification = 'U'
WITH LOCAL CHECK OPTION;
这将创建一个基于 comedies 视图的视图,仅显示 kind = 'Comedy' 和 classification = 'U' 的电影。任何尝试在视图中 INSERT 或 UPDATE 行的操作,如果新行不具有 classification = 'U',将被拒绝,但电影 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 ( ... ) 子句也是扩展,安全屏障视图和安全调用者视图也是如此。