视图概述¶
本主题涵盖理解和使用视图的概念。
本主题内容:
什么是视图?¶
视图允许像访问表一样访问查询结果。查询在 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 支持将视图定义为安全视图。有关安全视图的更多详细信息,请参阅 使用安全视图。
备注
If a user has enough privilege to access the content of a view, but has no access to the underlying table of the view, then the user cannot query the view unless the owner role of the view has access to the underlying table.
If a user has enough privilege to access the content of both the view and the underlying table of the view, the user can query the view successfully, regardless of whether the owner role of the view has access to the underlying table.
物化视图可以提高性能¶
物化视图旨在提高性能。物化视图包含表中数据子集的副本。根据表和物化视图中的数据量,扫描物化视图可能比扫描表快得多。物化视图还支持群集,您可以对同一数据创建多个物化视图,每个物化视图群集在不同的列上,以便不同的查询可以在具有该查询的最佳群集的视图上运行。
有关更多详细信息,请参阅 使用物化视图。
视图局限性¶
有关创建视图的限制和使用说明,请参阅 CREATE VIEW。
视图的定义无法更新(即不能使用 ALTER VIEW 或者 ALTER MATERIALIZED VIEW 更改视图的定义)。要更改视图定义,您必须使用新定义重新创建视图。
视图是只读的(即不能直接在视图上执行 DML 命令)。但是,您可以在对底层基表进行更新的 DML 语句内,通过子查询使用视图。例如:
DELETE FROM hospital_table WHERE cost > (SELECT AVG(cost) FROM accountant_view);
对表的更改不会自动传播到在该表上创建的视图。例如,如果删除表中的一列,则该表上的视图可能会变得无效。