视图概述

本主题涵盖理解和使用视图的概念。

本主题内容:

什么是视图?

视图允许像访问表一样访问查询结果。查询在 CREATE VIEW 语句中指定。

视图有多种用途,包括组合、隔离和保护数据。例如,您可以创建单独的视图,以满足不同类型员工(医院的医生和会计师)的需求:

CREATE TABLE hospital_table (patient_id INTEGER,
                             patient_name VARCHAR, 
                             billing_address VARCHAR,
                             diagnosis VARCHAR, 
                             treatment VARCHAR,
                             cost NUMBER(10,2));
INSERT INTO hospital_table 
        (patient_ID, patient_name, billing_address, diagnosis, treatment, cost) 
    VALUES
        (1, 'Mark Knopfler', '1982 Telegraph Road', 'Industrial Disease', 
            'a week of peace and quiet', 2000.00),
        (2, 'Guido van Rossum', '37 Florida St.', 'python bite', 'anti-venom', 
            70000.00)
        ;
Copy
CREATE VIEW doctor_view AS
    SELECT patient_ID, patient_name, diagnosis, treatment FROM hospital_table;

CREATE VIEW accountant_view AS
    SELECT patient_ID, patient_name, billing_address, cost FROM hospital_table;
Copy

视图几乎可以在任何可以使用表的地方使用(连接、子查询等)。例如,使用上面创建的视图:

  • 显示每位患者的所有类型的医疗问题:

    SELECT DISTINCT diagnosis FROM doctor_view;
    +--------------------+
    | DIAGNOSIS          |
    |--------------------|
    | Industrial Disease |
    | python bite        |
    +--------------------+
    
    Copy
  • 显示每次治疗的费用(不显示特定患者的个人识别信息):

    SELECT treatment, cost 
        FROM doctor_view AS dv, accountant_view AS av
        WHERE av.patient_ID = dv.patient_ID;
    +---------------------------+----------+
    | TREATMENT                 |     COST |
    |---------------------------+----------|
    | a week of peace and quiet |  2000.00 |
    | anti-venom                | 70000.00 |
    +---------------------------+----------+
    
    Copy

CREATE VIEW 命令可以使用完全限定、部分限定或不限定的表名。例如:

CREATE VIEW v1 AS SELECT ... FROM my_database.my_schema.my_table;

CREATE VIEW v1 AS SELECT ... FROM my_schema.my_table;

CREATE VIEW v1 AS SELECT ... FROM my_table;
Copy

如果未指定架构,则 Snowflake 假定该表 与视图处于相同的架构中。(如果假定表位于活动架构中,则视图可以在不同时间引用不同的表。)

视图类型

Snowflake 支持两种类型的视图:

  • 非物化视图(通常简称为“视图”)

  • 物化视图。

非物化视图

术语“视图”泛指所有类型的视图;然而,该术语在这里特指非物化视图。

视图基本上是查询的命名定义。非物化视图的结果是通过在查询中引用视图时执行查询来创建的。结果不会存储起来供将来使用。性能比物化视图慢。非物化视图是最常见的视图类型。

任何返回有效结果的查询表达式都可以用于创建非物化视图,例如:

  • 选择表中的部分(或全部)列。

  • 在表列中选择特定范围的数据。

  • 连接两个或多个表中的数据。

物化视图

虽然物化视图被命名为视图的一种,但在许多方面它的行为更像是表。物化视图的结果是存储起来的,几乎就像一个表。这样可以加快访问速度,但需要存储空间和主动维护,这两者都会产生额外的 成本

此外,物化视图还有一些非物化视图没有的限制。

有关更多详细信息,请参阅 使用物化视图

安全视图

非物化视图和物化视图都可以定义为 安全。与标准视图相比,安全视图具有一些优势,包括改善了数据隐私和数据共享;不过,它们也有一些性能影响需要考虑。

有关更多详细信息,请参阅 使用安全视图

递归视图(仅限非物化视图)

非物化视图可以是递归的(即视图可以引用自身)。

在视图中使用递归与在 递归 CTEs 中使用递归类似。事实上,视图可以用递归 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

您可以使用关键字 RECURSIVE 创建递归视图,而不是使用递归 CTE:

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

有关更多详细信息(包括示例),请参阅 CREATE VIEW

视图的优点

视图允许编写更多模块化代码

视图帮助您编写更清晰、模块化程度更高的 SQL 代码。例如,假设您的医院数据库有一个表,列出了所有员工的信息。您可以创建视图,以便方便地只提取医务人员或只提取有关维护人员的相关信息。您甚至可以创建视图层次结构。

例如,可以为医生和护士分别创建一个视图,然后通过引用医生视图和护士视图来创建 medical_staff 视图:

CREATE TABLE employees (id INTEGER, title VARCHAR);
INSERT INTO employees (id, title) VALUES
    (1, 'doctor'),
    (2, 'nurse'),
    (3, 'janitor')
    ;

CREATE VIEW doctors as SELECT * FROM employees WHERE title = 'doctor';
CREATE VIEW nurses as SELECT * FROM employees WHERE title = 'nurse';
CREATE VIEW medical_staff AS
    SELECT * FROM doctors
    UNION
    SELECT * FROM nurses
    ;
Copy
SELECT * 
    FROM medical_staff
    ORDER BY id;
+----+--------+
| ID | TITLE  |
|----+--------|
|  1 | doctor |
|  2 | nurse  |
+----+--------+
Copy

在许多情况下,您可以将查询分解为更小的部分,并为每个部分创建一个视图,而不是编写一个大型且难以理解的查询。这不仅使代码更易于理解,而且在许多情况下还使代码更易于调试,因为您可以一次调试一个视图,而不是整个查询。

一个视图可以被许多不同的查询引用,因此视图有助于提高代码的重用性。

视图允许授予对表的子集的访问权限

视图允许您仅授予对表中部分数据的访问权限。例如,假设您有一个患者记录表。医务人员应该有权访问所有医疗信息(例如诊断),但不能访问财务信息(例如患者的信用卡号)。会计人员应该有权访问与计费相关的信息,例如给患者开出的每张处方的费用,但不能访问私人医疗数据,例如心理健康状况的诊断。您可以创建两个单独的视图,一个用于医务人员,一个用于计费人员,以便每个角色只能看到执行其工作所需的信息。您可以通过视图实现这个目的,因为您可以将特定视图的权限授予特定角色,而被授权者角色无需拥有该视图下的表的权限。

以医疗为例:

  • 医务人员对数据表没有权限,但对显示诊断和治疗的视图有权限。

  • 会计人员对数据表没有权限,但对显示账单信息的视图有权限。

为了提高安全性,Snowflake 支持将视图定义为安全视图。有关安全视图的更多详细信息,请参阅 使用安全视图

物化视图可以提高性能

物化视图旨在提高性能。物化视图包含表中数据子集的副本。根据表和物化视图中的数据量,扫描物化视图可能比扫描表快得多。物化视图还支持群集,您可以对同一数据创建多个物化视图,每个物化视图群集在不同的列上,以便不同的查询可以在具有该查询的最佳群集的视图上运行。

有关更多详细信息,请参阅 使用物化视图

视图局限性

  • 有关创建视图的限制和使用说明,请参阅 CREATE VIEW

  • 视图的定义无法更新(即不能使用 ALTER VIEW 或者 ALTER MATERIALIZED VIEW 更改视图的定义)。要更改视图定义,您必须使用新定义重新创建视图。

  • 视图是只读的(即不能直接在视图上执行 DML 命令)。但是,您可以在对底层基表进行更新的 DML 语句内,通过子查询使用视图。例如:

    DELETE FROM hospital_table 
        WHERE cost > (SELECT AVG(cost) FROM accountant_view);
    
    Copy
  • 对表的更改不会自动传播到在该表上创建的视图。例如,如果删除表中的一列,则该表上的视图可能会变得无效。

语言: 中文