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)
如果希望视图提供行级安全性,应该使用这个参数。详见 第 41.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视图一起使用。 注意,只有在自动可更新的、没有INSTEAD OF触发器或者 INSTEAD规则的视图上才支持CHECK OPTION。 如果一个自动可更新的视图被定义在一个具有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;
访问中引用的表视图由视图所有者的权限确定。在某些情况下,这可用于提供对基础表的安全但受限制的访问。但是,并非所有观点都可以防范篡改。在视图中调用的函数的处理方式与使用视图直接从查询中调用的函数相同。因此,视图的用户必须具有调用视图使用的所有函数的权限。
在现有视图上使用 CREATE OR REPLACE VIEW时,仅更改视图定义的SELECT规则。其他视图属性(包括所有权,权限和非SELECT规则)保持不变。您必须拥有视图才能替换它(这包括成为拥有角色的成员)。
可更新视图
简单视图是自动可更新的:系统将允许在这类视图上以在常规表上相同的方式 使用INSERT、UPDATE以及 DELETE语句。如果一个视图满足以下条件,它就是自动 可更新的:
- 在该视图的FROM列表中刚好只有一项,并且它必须是一个 表或者另一个可更新视图。
- 视图定义的顶层不能包含WITH、DISTINCT、 GROUP BY、HAVING、 LIMIT或者OFFSET子句。
- 视图定义的顶层不能包含集合操作(UNION、 INTERSECT或者EXCEPT)。
- 视图的选择列表不能包含任何聚集、窗口函数或者集合返回函数。
一个自动可更新的视图可以混合可更新列以及不可更新列。如果一个列是对底层 基本关系中一个可更新列的简单引用,则它是可更新的。否则该列是只读的,并 且在一个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的操作符的条件)将在该视图使用者的任何条件 之前计算]。注意正因为这样,不会 被最终返回的行(因为它们不会通过用户的WHERE条件)可能 仍会结束被锁定的状态。可以用EXPLAIN来查看 哪些条件被应用在关系层面(并且因此不锁定行)以及哪些不会被应用在关系 层面。
一个更加复杂的不满足所有这些条件的视图默认是只读的:系统将不允许在 该视图上的插入、更新或者删除。可以通过在该视图上创建一个 INSTEAD OF触发器来获得可更新视图的效果,该触发器必须 把该视图上的尝试的插入等转换成其他表上合适的动作。更多信息请见CREATE TRIGGER。另一种可能性是创建规则(见 CREATE RULE),不过实际中触发器更容易理解和正确使用。
注意在视图上执行插入、更新或删除的用户必须具有该视图上相应的插入、 更新或删除特权。此外,视图的拥有者必须拥有底层基本关系上的相关特权, 但是执行更新的用户并不需要底层基本关系上的任何权限]。
示例
创建一个包含所有喜剧电影的视图:
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',在该视图中的任何 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的名称不能是方案限定的。