视图概述¶
本主题涵盖理解和使用视图的概念。
本主题内容:
什么是视图?¶
视图允许像访问表一样访问查询结果。查询在 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) ;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;
视图几乎可以在任何可以使用表的地方使用(连接、子查询等)。例如,使用上面创建的视图:
显示每位患者的所有类型的医疗问题:
SELECT DISTINCT diagnosis FROM doctor_view; +--------------------+ | DIAGNOSIS | |--------------------| | Industrial Disease | | python bite | +--------------------+
显示每次治疗的费用(不显示特定患者的个人识别信息):
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 | +---------------------------+----------+
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;
如果未指定架构,则 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 );
您可以使用关键字 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 );
有关更多详细信息(包括示例),请参阅 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 ;SELECT * FROM medical_staff ORDER BY id; +----+--------+ | ID | TITLE | |----+--------| | 1 | doctor | | 2 | nurse | +----+--------+
在许多情况下,您可以将查询分解为更小的部分,并为每个部分创建一个视图,而不是编写一个大型且难以理解的查询。这不仅使代码更易于理解,而且在许多情况下还使代码更易于调试,因为您可以一次调试一个视图,而不是整个查询。
一个视图可以被许多不同的查询引用,因此视图有助于提高代码的重用性。
视图允许授予对表的子集的访问权限¶
视图允许您仅授予对表中部分数据的访问权限。例如,假设您有一个患者记录表。医务人员应该有权访问所有医疗信息(例如诊断),但不能访问财务信息(例如患者的信用卡号)。会计人员应该有权访问与计费相关的信息,例如给患者开出的每张处方的费用,但不能访问私人医疗数据,例如心理健康状况的诊断。您可以创建两个单独的视图,一个用于医务人员,一个用于计费人员,以便每个角色只能看到执行其工作所需的信息。您可以通过视图实现这个目的,因为您可以将特定视图的权限授予特定角色,而被授权者角色无需拥有该视图下的表的权限。
以医疗为例:
医务人员对数据表没有权限,但对显示诊断和治疗的视图有权限。
会计人员对数据表没有权限,但对显示账单信息的视图有权限。
为了提高安全性,Snowflake 支持将视图定义为安全视图。有关安全视图的更多详细信息,请参阅 使用安全视图。
物化视图可以提高性能¶
物化视图旨在提高性能。物化视图包含表中数据子集的副本。根据表和物化视图中的数据量,扫描物化视图可能比扫描表快得多。物化视图还支持群集,您可以对同一数据创建多个物化视图,每个物化视图群集在不同的列上,以便不同的查询可以在具有该查询的最佳群集的视图上运行。
有关更多详细信息,请参阅 使用物化视图。
视图局限性¶
有关创建视图的限制和使用说明,请参阅 CREATE VIEW。
视图的定义无法更新(即不能使用 ALTER VIEW 或者 ALTER MATERIALIZED VIEW 更改视图的定义)。要更改视图定义,您必须使用新定义重新创建视图。
视图是只读的(即不能直接在视图上执行 DML 命令)。但是,您可以在对底层基表进行更新的 DML 语句内,通过子查询使用视图。例如:
DELETE FROM hospital_table WHERE cost > (SELECT AVG(cost) FROM accountant_view);
对表的更改不会自动传播到在该表上创建的视图。例如,如果删除表中的一列,则该表上的视图可能会变得无效。