SQL COMMAND · 表与视图
CREATE VIEW
定义一个新视图
CREATE表与视图引入 10(基线)现存至 20 devel0 次语法变更
- 动词
CREATE- 对象
VIEW- 分组
- 表与视图
- 引入版本
- 10(基线)
- 状态
- 现存
- 语法变更次数
- 0
- 手册小节数
- 6
版本轨迹
相对 PostgreSQL 17 无变化。
语法铁道图 PostgreSQL 18
沿轨道从左向右阅读,分岔表示选择,绕行表示可选,回环表示重复。方框为参数,点击带下划线的参数可展开子规则。
语法概要
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)如果该视图旨在提供行级安全,则应使用此选项。详见 Section 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;
默认情况下,访问视图中引用的底层基关系时,会依据视图所有者的权限进 行判断。在某些情况下,这可用于为底层表提供安全但受限的访问。然而, 并非所有视图都能防止被篡改;详见Section 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规则,都 保持不变。要替换该视图,你必须拥有它(这也包括成为拥有该视图的角色 的成员)。
可更新视图
简单视图是自动可更新的:系统允许像对普通表一样在视图上使用 INSERT、UPDATE、 DELETE和MERGE语句。满足下列所 有条件的视图是自动可更新的:
该视图的
FROM列表中必须恰好只有一项,而且这一 项必须是一个表或另一个可更新视图。视图定义的顶层不能包含
WITH、DISTINCT、GROUP BY、HAVING、LIMIT或者OFFSET子句。视图定义的顶层不能包含集合操作(
UNION、INTERSECT或者EXCEPT)。视图的
SELECT列表不能包含任何聚合、窗口函数或集合返回函数。
自动可更新视图可以同时包含可更新列和不可更新列。如果某列只是简单引 用了底层基关系中的一个可更新列,则该列是可更新的;否则,该列为只 读,如果INSERT、UPDATE或 MERGE语句试图为其赋值,就会报错。
如果视图是自动可更新的,系统会把视图上的任何 INSERT、UPDATE、 DELETE或MERGE语句转换为底层基 关系上的对应语句。带有ON CONFLICT UPDATE子句的 INSERT语句也得到完全支持。
如果自动可更新视图包含WHERE条件,那么在该视图上 执行UPDATE、DELETE和 MERGE语句时,该条件会限制底层基关系中哪些行可被 修改。不过,UPDATE或MERGE仍可 能把某一行改成不再满足WHERE条件,从而使其不再能 通过该视图看到。类似地,INSERT或 MERGE命令也可能插入不满足 WHERE条件的基关系行,因此这些行通过该视图不可见 (ON CONFLICT UPDATE也可能类似地影响现有的、通过 该视图不可见的行)。可以使用CHECK OPTION阻止 INSERT、UPDATE和 MERGE命令创建这类通过该视图不可见的行。
如果自动可更新视图带有security_barrier属性,那么 视图上的所有WHERE条件(以及任何使用标记为 LEAKPROOF的操作符的条件)总会先于视图使用者添加 的任何条件求值。详见Section 39.5。请注意,因此 那些最终不会返回的行(因为它们未通过用户的WHERE条 件)仍可能被锁定。可以使用EXPLAIN查看哪些条件是 在关系级别应用的(因而不会锁定行),哪些则不是。
默认情况下,更复杂且不满足上述全部条件的视图是只读的:系统不允许对 该视图执行INSERT、UPDATE、 DELETE或MERGE。可以通过在该视 图上创建INSTEAD OF触发器来获得可更新视图的效果, 这类触发器必须把针对该视图的插入等操作转换为在其他表上执行的适当动 作。更多信息请见CREATE TRIGGER。另一种可能性是 创建规则(见CREATE RULE),但在实践中,触发器 更容易理解和正确使用。另外请注意,带有规则的关系不支持 MERGE。
注意,在视图上执行插入、更新或删除的用户,必须拥有该视图上相应的插 入、更新或删除权限。另外,默认情况下,视图所有者必须在底层基关系上 拥有相关权限,而执行更新的用户则不需要在底层基关系上拥有任何权限 (参见Section 39.5)。但是,如果视图的 security_invoker设置为true,则 必须由执行更新的用户而非视图所有者,在底层基关系上拥有相关权限。
示例
创建一个由所有喜剧影片组成的视图:
CREATE VIEW comedies AS
SELECT *
FROM films
WHERE kind = 'Comedy';
这会创建一个视图,其中包含创建视图时films表中的各 列。尽管创建视图时使用了*,但以后添加到该表的列 不会成为该视图的一部分。
创建带有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 ( ... )子句同样是扩展,安全屏障视图和安 全调用者视图也是如此。
另见
语法演化
相邻大版本之间的差异,新的在前。版本号链接到对应快照。
PostgreSQL 20← 19正文更新
正文更新PostgreSQL 19← 18正文更新
正文更新PostgreSQL 14← 13正文更新
正文更新PostgreSQL 13← 12正文更新
正文更新PostgreSQL 12← 11正文更新
正文更新PostgreSQL 11← 10正文更新
正文更新
同组命令
| 命令 | 动词 | 对象 | 版本变动 | 最近变更 |
|---|---|---|---|---|
TRUNCATE | TRUNCATE | — | — | |
| 清空一个表或一组表 | 现存 | |||
CREATE MATERIALIZED VIEW | CREATE | MATERIALIZED VIEW | 121 次 | |
| 定义一个新物化视图 | 现存 | |||
ALTER MATERIALIZED VIEW | ALTER | MATERIALIZED VIEW | 142 次 | |
| 更改一个物化视图的定义 | 现存 | |||
DROP MATERIALIZED VIEW | DROP | MATERIALIZED VIEW | — | |
| 移除一个物化视图 | 现存 | |||
REFRESH MATERIALIZED VIEW | REFRESH | MATERIALIZED VIEW | — | |
| 替换物化视图的内容 | 现存 | |||
CREATE SEQUENCE | CREATE | SEQUENCE | 141 次 | |
| 定义一个新的序列发生器 | 现存 | |||
ALTER SEQUENCE | ALTER | SEQUENCE | 141 次 | |
| 更改序列发生器的定义 | 现存 | |||
DROP SEQUENCE | DROP | SEQUENCE | — | |
| 移除一个序列 | 现存 | |||
CREATE TABLE | CREATE | TABLE | 206 次 | |
| 定义一个新表 | 现存 | |||
ALTER TABLE | ALTER | TABLE | 206 次 | |
| 更改一个表的定义 | 现存 | |||
DROP TABLE | DROP | TABLE | — | |
| 移除一个表 | 现存 | |||
CREATE TABLE AS | CREATE | TABLE AS | 192 次 | |
| 根据查询结果定义一个新表 | 现存 | |||
CREATE VIEW | CREATE | VIEW | — | |
| 定义一个新视图 | 现存 | |||
ALTER VIEW | ALTER | VIEW | 142 次 | |
| 更改视图的定义 | 现存 | |||
DROP VIEW | DROP | VIEW | — | |
| 移除一个视图 | 现存 | |||