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 RECURSIVEview_name
(column_names
) AS (SELECT...
) SELECTcolumn_names
FROMview_name
;对于一个递归视图必须指定一个视图列名列表。
name
-
要创建的视图的名字(可以是模式限定的)。
column_name
-
要用于视图列的名称列表,可选。如果没有给出,列名会根据查询 推导。
WITH (
view_option_name
[=view_option_value
] [, ... ] )-
这个子句为视图指定一些可选的参数,支持下列参数:
check_option
(enum
)-
这个参数可以是
local
或者cascaded
,并且它 等效于指定WITH [ CASCADED | LOCAL ] CHECK OPTION
(见下文)。 可以使用ALTER VIEW在一个现有视图上修改这个选项。 security_barrier
(boolean
)-
如果希望视图提供行级安全性,应该使用这个参数。详见 第 40.5 节。
query
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;
对视图中引用的表的访问由视图拥有者的权限决定。在某些情况下,这可以 被用来提供安全但是受限的底层表访问。不过,并非所有视图都对篡改是安 全的,详见第 40.5 节。在视图中调用的函数会被 同样对待,就好像是直接在使用该视图的查询中调用它们一样。因此,一个 视图的用户必须具有调用视图所使用的全部函数的权限。
当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
的操作符的条件)将在该视图使用者的任何条件 之前计算。详见第 40.5 节。注意正因为这样,不会
被最终返回的行(因为它们不会通过用户的WHERE
条件)可能 仍会结束被锁定的状态。可以用EXPLAIN
来查看 哪些条件被应用在关系层面(并且因此不锁定行)以及哪些不会被应用在关系 层面。
一个更加复杂的不满足所有这些条件的视图默认是只读的:系统将不允许在 该视图上的插入、更新或者删除。可以通过在该视图上创建一个 INSTEAD OF
触发器来获得可更新视图的效果,该触发器必须 把该视图上的尝试的插入等转换成其他表上合适的动作。更多信息请见CREATE TRIGGER。另一种可能性是创建规则(见
CREATE RULE
),不过实际中触发器更容易理解和正确使用。
注意在视图上执行插入、更新或删除的用户必须具有该视图上相应的插入、 更新或删除特权。此外,视图的拥有者必须拥有底层基本关系上的相关特权, 但是执行更新的用户并不需要底层基本关系上的任何权限(见 第 40.5 节)。
示例
创建一个由所有喜剧电影组成的视图:
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的名称不能是方案限定的。
兼容性
CREATE OR REPLACE VIEW
是一种 PostgreSQL的语言扩展。临时 视图的概念也是这样。WITH ( ... )
子句也是一种扩展。