PostgreSQL 9.4.4 中文手册
上一页 | 上一级 |  | 下一页

# 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 name (columns) AS SELECT ...;

  等同于

      CREATE VIEW name AS WITH RECURSIVE name (columns) AS (SELECT ...) SELECT columns FROM 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` (`string`)

    如果视图打算提供行级别的安全就应该使用这个选项。参阅 第 38.5 节获取全部信息。

`query`

  一个将为视图提供行和列的SELECT 或VALUES语句。

`WITH [ CASCADED | LOCAL ] CHECK OPTION`

  这个选项控制自动可更新视图的行为。给出时，对视图的`INSERT` 和`UPDATE`都要检查以确保新行满足视图定义的条件（也就是说， 新行应该可以通过视图看到）。如果没有通过检查，更新将被拒绝。 如果没有声明`CHECK OPTION`，将允许对视图的`INSERT` 和`UPDATE`命令创建通过该视图不可见的行。 支持下列的检查选项：

  `LOCAL`

    只对视图本身直接定义的条件检查新行。任何底层基础视图定义的条件都不检查 （除非它们也声明了`CHECK OPTION`）。

  `CASCADED`

    针对该视图和所有底层基础视图的条件检查新行。如果声明了`CHECK OPTION`， 并且没有声明`LOCAL`也没有声明`CASCADED`， 那么假设是`CASCADED`。

  `RECURSIVE`视图不能使用`CHECK OPTION`。

  请注意，只在可自动更新、并且没有`INSTEAD OF`触发器或`INSTEAD` 规则的视图上支持`CHECK OPTION`。如果一个可自动更新的视图定义在一个拥有 `INSTEAD OF`触发器的基础视图的上面，那么会使用`LOCAL CHECK OPTION` 检查可自动更新视图上的条件，但是不会检查带有`INSTEAD OF` 触发器的基础视图上的条件（级联的检查选项将不会级联到一个触发器可更新的视图， 并且任何直接定义在触发器可更新视图上的检查选项将被忽略）。 如果该视图或者任何它的基础关系有一个`INSTEAD`规则， 导致`INSERT`或`UPDATE`命令重写， 那么所有检查选项都将在重写的查询中忽略，包括任何来自定义在`INSTEAD` 规则的关系上的可自动更新视图的检查。

## 注意

使用DROP VIEW语句删除视图。

请注意视图字段的名字和类型不一定是你们期望的那样。比如，

    CREATE VIEW vista AS SELECT 'Hello World';

在两个方面很糟糕：字段名缺省是`?column?` 并且字段的数据类型缺省是`unknown`。 如果你想视图的结果是一个字符串文本，那么请像下面这样使用：

    CREATE VIEW vista AS SELECT text 'Hello World' AS hello;

对视图引用的表的访问的权限由视图的所有者决定。在一些情况下， 这可用于提供安全但是限制访问底层表。不过，不是所有视图对于篡改都是安全的； 参阅第 38.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`语句为相应的底层基本关系上的语句。

如果一个自动可更新的视图包含一个`WHERE`条件， 那么该条件约束基本关系的哪些行可以被视图上的`UPDATE` 和`DELETE`语句修改。不过，允许`UPDATE` 更改一个行，使得它不再满足`WHERE`条件，并且因此不再通过视图可见。 相似的，`INSERT`命令也可以插入不满足`WHERE` 条件的基本关系行，并且因此对这个视图不可见。`CHECK OPTION` 可以用来阻止`INSERT`和`UPDATE`命令创建该视图不可见的行。

如果一个可自动更新的视图标记为`security_barrier`， 那么所有视图的`WHERE`条件（和任何使用标记为 `LEAKPROOF`的操作符的条件）将总是在视图的用户添加任何条件之前评估。 参阅第 38.5 节获取全部信息。请注意， 由于这个原因，不是最终返回的行（因为它们不通过用户的`WHERE`条件） 最终可能仍然被锁。可以使用`EXPLAIN`查看哪个条件应用在了关系级别 （并且因此没有锁定行）。

不满足所有这些条件的更复杂的视图缺省是只读的：系统将不允许在该视图上插入、 更新或删除。可以通过在该视图上创建`INSTEAD OF`触发器获得可更新视图的效果， 该触发器必须转换在该视图上的尝试插入等为其他表上的适当动作。更多信息请参见 CREATE TRIGGER。还有一种可能性是创建规则 （参阅CREATE RULE），但是实际上触发器更容易理解和正确使用。

请注意，用户在视图上执行插入、更新或删除必须在该视图上有相应的插入、 更新或删除的权限。此外，视图的所有者必须在底层基础关系上有相关的权限， 但是执行更新的用户不需要在底层基础关系上的任何权限 （参阅第 38.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 nums_1_100 (n) AS
        VALUES (1)
    UNION ALL
        SELECT n+1 FROM nums_1_100 WHERE n < 100;

## 兼容性

`CREATE OR REPLACE VIEW`是PostgreSQL 的扩展。临时视图的概念也是扩展。`WITH ( ... )`子句也是一个扩展。

## 又见

ALTER VIEW, DROP VIEW, CREATE MATERIALIZED VIEW

上一页 | 起始页 | 下一页
CREATE USER MAPPING | 上一级 | DEALLOCATE