CREATE VIEW

基于对一个或多个现有表(或任何其他有效查询表达式)的查询,在当前/指定的架构中创建新视图。

该命令支持以下变体:

另请参阅:

ALTER VIEWDROP VIEWSHOW VIEWSDESCRIBE VIEW

CREATE OR ALTER <对象>

语法

CREATE [ OR REPLACE ] [ SECURE ] [ { [ { LOCAL | GLOBAL } ] TEMP | TEMPORARY | VOLATILE } ] [ RECURSIVE ] VIEW [ IF NOT EXISTS ] <name>
  [ ( <column_list> ) ]
  [ <col1> [ WITH ] MASKING POLICY <policy_name> [ USING ( <col1> , <cond_col1> , ... ) ]
           [ WITH ] PROJECTION POLICY <policy_name>
           [ WITH ] TAG ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] ) ]
  [ , <col2> [ ... ] ]
  [ [ WITH ] ROW ACCESS POLICY <policy_name> ON ( <col_name> [ , <col_name> ... ] ) ]
  [ [ WITH ] TAG ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] ) ]
  [ WITH CONTACT ( <purpose> = <contact_name> [ , <purpose> = <contact_name> ... ] ) ]
  [ CHANGE_TRACKING = { TRUE | FALSE } ]
  [ COPY GRANTS ]
  [ COMMENT = '<string_literal>' ]
  [ [ WITH ] ROW ACCESS POLICY <policy_name> ON ( <col_name> [ , <col_name> ... ] ) ]
  [ [ WITH ] AGGREGATION POLICY <policy_name> [ ENTITY KEY ( <col_name> [ , <col_name> ... ] ) ] ]
  [ [ WITH ] JOIN POLICY <policy_name> [ ALLOWED JOIN KEYS ( <col_name> [ , ... ] ) ] ]
  [ [ WITH ] TAG ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] ) ]
  AS <select_statement>
Copy

变体语法

CREATE OR ALTER VIEW

如果视图尚不存在,则创建新视图;或者更新现有视图的属性以匹配语句中定义的属性。CREATE OR ALTER VIEW 语句遵循 CREATE VIEW 语句的语法规则,并具有与 ALTER VIEW 语句相同的限制。

CREATE OR ALTER VIEW 命令不支持在视图创建后更改视图定义。此限制继承自 ALTER VIEW 命令。

支持以下修改:

  • 转换为安全视图(或从安全视图恢复)。

  • 添加、覆盖、移除视图或视图列的注释。

  • 启用或禁用视图的变更跟踪。

有关更多信息,请参阅 CREATE OR ALTER VIEW 使用说明CREATE OR ALTER <对象>

CREATE OR ALTER [ SECURE ] [ { [ { LOCAL | GLOBAL } ] TEMP | TEMPORARY | VOLATILE } ] [ RECURSIVE ] VIEW <name>
  [ ( <column_list> ) ]
  [ CHANGE_TRACKING =  { TRUE | FALSE } ]
  [ COMMENT = '<string_literal>' ]
  AS <select_statement>
Copy

必填参数

name

指定视图的标识符;对于在其中创建视图的架构来说,此标识符必须是唯一的。

此外,标识符必须以字母字符开头,且不能包含空格或特殊字符,除非整个标识符字符串放在双引号内(例如,"My object")。放在双引号内的标识符也区分大小写。

有关更多详细信息,请参阅 标识符要求

select_statement

指定用于创建视图的查询。可以位于一个或多个源表或任何其他有效 SELECT 语句上。此查询用作视图的文本/定义,并显示在 SHOW VIEWS 输出和 VIEWS Information Schema 视图中。

可选参数

SECURE

指定视图为安全视图。有关安全视图的详细信息,请参阅 使用安全视图

默认:无值(视图不是安全视图)

{ [ { LOCAL | GLOBAL } ] TEMP | TEMPORARY | VOLATILE }

指定该视图仅在创建该视图的 会话 期间持续存在。临时视图及其所有内容将在会话结束时删除。

提供 TEMPORARY (例如 GLOBAL TEMPORARY)的同义词和缩写是为了与其他数据库兼容(例如,防止在迁移 CREATE VIEW 语句时出错)。使用这些关键字中的任何一个创建的视图的外观和行为与使用 TEMPORARY 关键字创建的视图相同。

默认:无值。如果视图未声明为 TEMPORARY,则该视图是永久视图。

如果希望避免意外冲突,请避免以架构中已经存在的视图命名临时视图。

如果创建了一个与架构中另一个视图同名的临时视图,那么对该视图执行的所有查询和操作只影响会话中的临时视图,直到删除临时视图为止。如果删除视图,则删除临时视图,而不是架构中已存在的视图。

RECURSIVE

指定视图可以使用递归语法引用自身,而不必使用 CTE(公共表表达式)。有关递归视图的更多信息,特别是 RECURSIVE 关键字,请参阅 递归视图(仅限非物化视图) (仅限非物化视图)和下面的递归视图示例。

默认:无值(视图不是递归的,或者仅通过使用 CTE 递归)

column_list

如果您希望在新视图中更改列的名称或向列添加注释,请包含一个列列表,该列表指定列名和(如果需要)关于列的注释。(无需指定列的数据类型。)

如果视图中的任何列都基于表达式(而不仅仅是简单的列名),则必须为视图中的每个列提供列名。例如,在以下情况下,列名是必需的:

CREATE VIEW v1 (pre_tax_profit, taxes, after_tax_profit) AS
    SELECT revenue - cost, (revenue - cost) * tax_rate, (revenue - cost) * (1.0 - tax_rate)
    FROM table1;
Copy

您可以为每列指定可选注释。例如:

CREATE VIEW v1 (pre_tax_profit COMMENT 'revenue minus cost',
                taxes COMMENT 'assumes taxes are a fixed percentage of profit',
                after_tax_profit)
    AS
    SELECT revenue - cost, (revenue - cost) * tax_rate, (revenue - cost) * (1.0 - tax_rate)
    FROM table1;
Copy

当列名不明确时,注释特别有用。

要查看注释,请使用 DESCRIBE VIEW

MASKING POLICY = policy_name

指定要在列上设置的 掩码策略

USING ( col_name , cond_col_1 ... )

指定要传递到条件掩码策略 SQL 表达式的实参。

列表中的第一列指定用于掩码处理或标记数据的策略条件的列,并且 必须 与设置掩码策略的列匹配。

附加列指定要评估的列,以确定在对第一列进行查询时是否对查询结果的每行中的数据进行掩码处理或标记化。

如果省略 USING 子句,Snowflake 会将条件掩码策略视为正常的 掩码策略

PROJECTION POLICY policy_name

指定要在列上设置的 投影策略

CHANGE_TRACKING = { TRUE | FALSE }

指定是否对视图启用变更跟踪。

  • TRUE 会对视图启用变更跟踪。此设置将一对隐藏列添加到源表中,并开始在列中存储变更跟踪元数据。这些列会占用少量存储空间。

    可以使用 SELECT 语句的 CHANGES 子句查询变更跟踪元数据,也可以通过在表上创建和查询一个或多个流来查询变更跟踪元数据。

  • FALSE 不会对视图启用更改跟踪。

COPY GRANTS

使用 OR REPLACE 子句创建新视图时保留原始视图的访问权限。

该参数将现有视图中的所有权限( OWNERSHIP 除外)复制到新视图中。新视图 不会 继承为架构中的对象类型定义的任何未来授权。默认情况下,执行 CREATE VIEW 语句的角色拥有新视图。

如果该参数未包含在 CREATE VIEW 语句中,则新视图 不会 继承对原始视图授予的任何显式访问权限,但会继承为架构中的对象类型定义的任何未来授权。

请注意,复制授权的操作在 CREATE VIEW 语句中(即在同一事务中)自动发生。

默认:无值(不复制授权)

COMMENT = 'string_literal'

指定视图的注释。

默认:无值

ROW ACCESS POLICY policy_name ON ( col_name [ , col_name ... ] )

指定要在视图上设置的 行访问策略

AGGREGATION POLICY policy_name [ ENTITY KEY ( col_name [ , col_name ... ] ) ]

指定要在视图上设置的 聚合策略

使用可选的 ENTITY KEY 参数来定义视图中哪些列可以唯一地标识实体。有关更多信息,请参阅 通过聚合策略实施实体级隐私

JOIN POLICY policy_name [ ALLOWED JOIN KEYS ( col_name [ , ... ] ) ]

指定要在视图上设置的 联接策略

使用可选的 ALLOWED JOIN KEYS 参数,定义当此策略生效时允许将哪些列用作联接列。有关更多信息,请参阅 联接策略

CREATE OR ALTER 变体语法不支持此参数。

TAG ( tag_name = 'tag_value' [ , tag_name = 'tag_value' , ... ] )

指定 标签 名称和标签字符串值。

标签值始终为字符串,标签值的最大字符数为 256。

有关在语句中指定标签的信息,请参阅 Tag quotas

WITH CONTACT ( purpose = contact [ , purpose = contact ...] )

将新对象与一个或多个 联系人 关联。

访问控制要求

用于执行此操作的 角色 必须至少具有以下 权限

权限

对象

备注

CREATE VIEW

架构

创建新视图时需要。

SELECT

表、外部表、视图

在视图定义中查询的任何表和/或视图上都是必需的。

APPLY

掩码策略、行访问策略、标签

仅在创建视图时应用掩码策略、行访问策略、对象标签或这些 治理 功能的任何组合时才需要。

OWNERSHIP

视图

  • 若要创建创建与架构中已存在的对象同名的临时对象,必须授予角色或使其继承对象上的 OWNERSHIP 权限。

  • 现有 视图执行 CREATE OR ALTER VIEW 语句时需要。

OWNERSHIP is a special privilege on an object that is automatically granted to the role that created the object, but can also be transferred using the GRANT OWNERSHIP command to a different role by the owning role (or any role with the MANAGE GRANTS privilege).

Note that in a managed access schema, only the schema owner (i.e. the role with the OWNERSHIP privilege on the schema) or a role with the MANAGE GRANTS privilege can grant or revoke privileges on objects in the schema, including future grants.

Operating on an object in a schema requires at least one privilege on the parent database and at least one privilege on the parent schema.

有关创建具有指定权限集的自定义角色的说明,请参阅 创建自定义角色

有关对 安全对象 执行 SQL 操作的相应角色和权限授予的一般信息,请参阅 访问控制概述

一般使用说明

  • 视图定义可以包含 ORDER BY 子句(例如 create view v1 as select * from t1 ORDER BY column1)。但是,Snowflake 建议从大多数视图定义中 排除 ORDER BY 子句。若视图在不需要排序的情况下被使用,那么添加 ORDER BY 子句就会带来不必要的计算开销。例如,当视图用于联接,而联接列与 ORDER BY 列不同时,通常对视图结果进行排序的额外成本都会浪费掉。如果需要对查询结果进行排序,通常在使用视图的查询中指定,而不是在视图本身中指定 ORDER BY

  • 如果在视图定义中指定 CURRENT_DATABASECURRENT_SCHEMA 函数,该函数会返回包含视图的数据库或架构,而不是用于会话的数据库或架构。

  • 视图的定义限制为 95KB。

  • 嵌套级别最多限制为 20 个。尝试创建嵌套超过 20 次的视图将会失败。

  • 视图定义不是动态的。如果修改了基础源,使其不再与视图定义匹配,则视图不会自动更新,尤其是在删除列时。例如:

    • 在源表中创建一个引用特定列的视图,然后从表中删除该列。

    • 使用 SELECT * 从表创建视图,并对表中的列进行更改,例如:

      • 删除一列。

      • 添加一列。

      • 更改列顺序。

    在这些情况下,查询视图将返回与列相关的错误。

  • 如果删除了视图的源表,则查询该视图将返回 object does not exist 错误。

  • 架构不能包含同名的表和视图。如果架构中已存在同名的表,则 CREATE VIEW 语句将产生错误。

  • 当创建视图时,对表和其他数据库对象的 :doc:` 非限定 </sql-reference/name-resolution>` 引用 :emph:` 在视图的架构中 ` 解析,而不是在会话的当前架构中解析。同样,部分限定的对象(即 schema.object)在视图的数据库中解析,而不是在会话的当前数据库中解析。

    将忽略 SEARCH_PATH 会话参数(如果存在)。

  • 使用 OR REPLACE 相当于对现有视图执行 DROP VIEW,然后创建具有相同名称的新视图。

    CREATE OR REPLACE <object> 语句是原子的。也就是说,当对象被替换时,旧对象将被删除,新对象将在单个事务中创建。

    这意味着使用 CREATE OR REPLACE VIEW 操作执行任何并行查询都使用旧的或新的视图版本。

    重新创建或交换视图会丢弃其更改数据,从而使视图上的任何流都过时。过时 的流是不可读的。

  • OR REPLACEIF NOT EXISTS 子句互斥。它们不能同时用于同一条语句中。

  • 使用 COPY GRANTS

    • 数据共享:

      • 如果现有安全视图已共享到另一个账户,则替换视图也会共享。

      • 如果现有安全视图已作为数据使用者与您的账户共享,并且进一步授予了对账户中其他角色的访问权限(在父数据库上使用 GRANT IMPORTED PRIVILEGES),则还会授予对替换视图的访问权限。

    • 替换视图的 SHOW GRANTS 输出会将复制权限的获得者列为执行 CREATE VIEW 语句的角色,并附带执行语句时的当前时间戳。

  • 当您创建视图,然后将该视图的权限授予角色时,即使该角色对视图访问的基础表没有权限,该角色也可以使用该视图。这意味着您可以创建一个视图,以便仅向角色授予对表子集的访问权限。例如,您可以创建一个视图,该视图访问同一表中的医疗账单信息,但不访问医疗诊断信息。然后,您可以将该视图的权限授予“会计师”角色,以便会计师可以在不查看患者诊断信息的情况下查看账单信息。

  • 根据设计,该 SHOW VIEWS 命令不提供有关安全视图的信息。若要查看有关安全视图的信息,必须使用 Information Schema 中的 VIEWS 视图,并且必须使用拥有该视图的角色。

  • 递归视图必须提供列名列表。

  • 定义递归视图时,请防止无限递归。递归视图定义中的 WHERE 子句应使递归最终停止,通常是在处理完数据层次结构的最后一层后耗尽数据。

  • 关于元数据:

    注意

    客户应确保在使用 Snowflake 服务时,不会将个人数据(用户对象除外)、敏感数据、出口管制数据或其他受监管数据作为元数据输入。有关更多信息,请参阅 Snowflake 中的元数据字段

  • 在一个或多个视图列上使用掩码策略创建视图或将行访问策略添加到视图时,请使用 POLICY_CONTEXT 函数模拟对受掩码策略保护的列和受行访问策略保护的视图的查询。

  • 请勿创建将流作为源对象的视图,除非同一个角色同时拥有视图和源流(即,同一个角色,或者角色层次结构中较低的角色,对视图和源流拥有 OWNERSHIP 权限)。相反,创建具有要跟踪的对象作为源对象的视图。然后,在这些视图上创建流。有关更多信息,请参阅 视图上的流

移植说明

  • 一些供应商支持 FORCE 关键字:

    CREATE OR REPLACE FORCE VIEW ...
    
    Copy

    Snowflake 接受 FORCE 关键字,但不支持它。换言之,如果使用此关键字,则不会出现语法错误,但如果基础数据库对象(表或视图)尚不存在,则使用 FORCE 不会强制创建视图。即使使用了 FORCE 关键字,尝试创建不存在的表或视图的视图也会导致错误消息。

  • 在视图中查找表时,某些供应商会在活动架构中搜索非限定表名称;Snowflake 在 :ref:` 与视图相同的模式 <label-views_introduction__unqualified_table_schema_equals_view_schema>` 中搜索未限定表名。移植到 Snowflake 时,请考虑更新视图以使用完全限定的表名。

CREATE OR ALTER VIEW 使用说明

  • ALTER VIEW 命令的所有限制均适用。

  • 此命令 支持以下操作:

    • 更改视图的定义。

    • 使用 RENAME TO 参数重命名视图。

    • 添加或更改标签和策略。任何现有标签和策略都会得到保留。

    • 将 TEMPORARY 视图转换为永久视图,反之亦然。

示例

基本示例

在当前架构中创建一个带有注释的视图,该视图从表中选择所有行:

CREATE VIEW myview COMMENT='Test view' AS SELECT col1, col2 FROM mytable;

SHOW VIEWS;

+---------------------------------+-------------------+----------+---------------+-------------+----------+-----------+--------------------------------------------------------------------------+
| created_on                      | name              | reserved | database_name | schema_name | owner    | comment   | text                                                                     |
|---------------------------------+-------------------+----------+---------------+-------------+----------+-----------+--------------------------------------------------------------------------|
| Thu, 19 Jan 2017 15:00:37 -0800 | MYVIEW            |          | MYTEST1       | PUBLIC      | SYSADMIN | Test view | CREATE VIEW myview COMMENT='Test view' AS SELECT col1, col2 FROM mytable |
+---------------------------------+-------------------+----------+---------------+-------------+----------+-----------+--------------------------------------------------------------------------+
Copy

下一个示例与上一个示例相同,只是视图是安全的:

CREATE OR REPLACE SECURE VIEW myview COMMENT='Test secure view' AS SELECT col1, col2 FROM mytable;

SELECT is_secure FROM information_schema.views WHERE table_name = 'MYVIEW';
Copy

下面显示了创建递归视图的两种方法:

第一,创建并加载表:

CREATE OR REPLACE TABLE employees (title VARCHAR, employee_ID INTEGER, manager_ID INTEGER);
Copy
INSERT INTO employees (title, employee_ID, manager_ID) VALUES
    ('President', 1, NULL),  -- The President has no manager.
        ('Vice President Engineering', 10, 1),
            ('Programmer', 100, 10),
            ('QA Engineer', 101, 10),
        ('Vice President HR', 20, 1),
            ('Health Insurance Analyst', 200, 20);
Copy

使用递归 CTE 创建视图,然后查询该视图。

CREATE VIEW employee_hierarchy (title, employee_ID, manager_ID, "MGR_EMP_ID (SHOULD BE SAME)", "MGR TITLE") AS (
   WITH RECURSIVE employee_hierarchy_cte (title, employee_ID, manager_ID, "MGR_EMP_ID (SHOULD BE SAME)", "MGR TITLE") AS (
      -- Start at the top of the hierarchy ...
      SELECT title, employee_ID, manager_ID, NULL AS "MGR_EMP_ID (SHOULD BE SAME)", 'President' AS "MGR TITLE"
        FROM employees
        WHERE title = 'President'
      UNION ALL
      -- ... and work our way down one level at a time.
      SELECT employees.title, 
             employees.employee_ID, 
             employees.manager_ID, 
             employee_hierarchy_cte.employee_id AS "MGR_EMP_ID (SHOULD BE SAME)", 
             employee_hierarchy_cte.title AS "MGR TITLE"
        FROM employees INNER JOIN employee_hierarchy_cte
       WHERE employee_hierarchy_cte.employee_ID = employees.manager_ID
   )
   SELECT * 
      FROM employee_hierarchy_cte
);
Copy
SELECT * 
    FROM employee_hierarchy 
    ORDER BY employee_ID;
+----------------------------+-------------+------------+-----------------------------+----------------------------+
| TITLE                      | EMPLOYEE_ID | MANAGER_ID | MGR_EMP_ID (SHOULD BE SAME) | MGR TITLE                  |
|----------------------------+-------------+------------+-----------------------------+----------------------------|
| President                  |           1 |       NULL |                        NULL | President                  |
| Vice President Engineering |          10 |          1 |                           1 | President                  |
| Vice President HR          |          20 |          1 |                           1 | President                  |
| Programmer                 |         100 |         10 |                          10 | Vice President Engineering |
| QA Engineer                |         101 |         10 |                          10 | Vice President Engineering |
| Health Insurance Analyst   |         200 |         20 |                          20 | Vice President HR          |
+----------------------------+-------------+------------+-----------------------------+----------------------------+
Copy

使用关键字 RECURSIVE 创建视图,然后查询该视图。

CREATE RECURSIVE VIEW employee_hierarchy_02 (title, employee_ID, manager_ID, "MGR_EMP_ID (SHOULD BE SAME)", "MGR TITLE") AS (
      -- Start at the top of the hierarchy ...
      SELECT title, employee_ID, manager_ID, NULL AS "MGR_EMP_ID (SHOULD BE SAME)", 'President' AS "MGR TITLE"
        FROM employees
        WHERE title = 'President'
      UNION ALL
      -- ... and work our way down one level at a time.
      SELECT employees.title, 
             employees.employee_ID, 
             employees.manager_ID, 
             employee_hierarchy_02.employee_id AS "MGR_EMP_ID (SHOULD BE SAME)", 
             employee_hierarchy_02.title AS "MGR TITLE"
        FROM employees INNER JOIN employee_hierarchy_02
        WHERE employee_hierarchy_02.employee_ID = employees.manager_ID
);
Copy
SELECT * 
    FROM employee_hierarchy_02 
    ORDER BY employee_ID;
+----------------------------+-------------+------------+-----------------------------+----------------------------+
| TITLE                      | EMPLOYEE_ID | MANAGER_ID | MGR_EMP_ID (SHOULD BE SAME) | MGR TITLE                  |
|----------------------------+-------------+------------+-----------------------------+----------------------------|
| President                  |           1 |       NULL |                        NULL | President                  |
| Vice President Engineering |          10 |          1 |                           1 | President                  |
| Vice President HR          |          20 |          1 |                           1 | President                  |
| Programmer                 |         100 |         10 |                          10 | Vice President Engineering |
| QA Engineer                |         101 |         10 |                          10 | Vice President Engineering |
| Health Insurance Analyst   |         200 |         20 |                          20 | Vice President HR          |
+----------------------------+-------------+------------+-----------------------------+----------------------------+
Copy

CREATE OR ALTER VIEW 示例

基本示例

创建具有一列的表 my_table

CREATE OR ALTER TABLE my_table(a INT);
Copy

创建名为 v2 且从表格 my_table 中选择列 a 的视图:

CREATE OR ALTER VIEW v2(one)
  AS SELECT a FROM my_table;
Copy

创建或更改视图 v2。添加或更新视图的 COMMENT 和 CHANGE_TRACKING 的属性:

CREATE OR ALTER VIEW v2(one)
  COMMENT = 'fff'
  CHANGE_TRACKING = true
  AS SELECT a FROM my_table;
Copy

创建或更改视图 v2 以向列添加注释:

CREATE OR ALTER VIEW v2(one COMMENT 'bar')
  COMMENT = 'foo'
  AS SELECT a FROM my_table;
Copy

取消设置先前针对视图设置的属性

CREATE OR ALTER VIEW 语句中 缺少先前设置的属性 会导致该属性被取消设置。在下面的示例中,取消设置前面的示例中视图 v2 的 COMMENT 属性:

CREATE OR ALTER VIEW v2(one COMMENT 'bar')
  CHANGE_TRACKING = true
  AS SELECT a FROM my_table;
Copy
语言: 中文