🙏 感谢您的支持! 我们在七月份已经筹集了 $65 — 这足够我们工作到下个月。请帮助我们保持进度,进一步支持这个项目。 支持这个项目 →
SQL 代码已复制到剪贴板

课程 9.4 · 阅读时间:约 8 分钟

本课程介绍视图 (VIEW),这是一种 SQL 对象,允许您将查询保存为一个名称,然后像常规表一样使用它。您将学习如何创建视图,它们与表和临时表的区别,以及它们在某些任务中特别有用的地方。在本课程结束时,您将能够自信地使用视图来简化复杂查询和重用逻辑。

SQL 中的视图 (VIEW)

在上一课中,我们讨论了临时表,它们有助于在会话期间存储中间结果。现在让我们看看另一种重要的 SQL 工具:视图。它们也有助于简化复杂查询的工作,但方式不同。

视图允许您将 SELECT 查询保存为一个单独的名称,然后在后续使用中重用。这在报告、分析以及需要多次读取相同结果集的场景中特别有用。

SQL 视图

什么是视图

视图 (VIEW) 是一个数据库对象,它存储的不是数据本身,而是用于检索数据的 SQL 查询。

简单来说,视图可以被看作是一个“虚拟表”:

  • 它有一个名称;
  • 它可以用 SELECT 查询;
  • 它通常显示来自一个或多个表的数据;
  • 它有助于在更简单的接口后隐藏复杂的查询逻辑。

当您查询视图时,DBMS 通常会执行存储的查询,并根据底层表返回当前结果。

基本语法

视图是通过 CREATE VIEW 创建的:

CREATE VIEW view_name AS
SELECT column1, column2, column3
FROM table_name
WHERE condition;

之后,您可以像查询表一样查询视图:

SELECT *
FROM view_name;

重要的是要理解,常规视图存储的是查询逻辑,而不是结果的单独副本。

如果视图不再需要,您可以使用 DROP VIEW 将其删除:

DROP VIEW view_name;

在许多 DBMS 中,更安全的选项是 DROP VIEW IF EXISTS view_name;,它仅在对象存在时删除该对象,并有助于避免部署脚本中的错误。

示例:创建视图

假设我们经常想要获取客户及其支付总额的列表。我们可以创建一个视图,而不是每次都写相同的查询:

CREATE VIEW customer_payment_summary AS
SELECT c.customer_id,
       c.first_name,
       c.last_name,
       SUM(p.amount) AS total_amount,
       COUNT(p.payment_id) AS payment_count
FROM customer c
JOIN payment p ON c.customer_id = p.customer_id
GROUP BY c.customer_id, c.first_name, c.last_name;

现在,这个逻辑更容易使用:

SELECT customer_id, first_name, last_name, total_amount
FROM customer_payment_summary
ORDER BY total_amount DESC;

SELECT AVG(total_amount) AS avg_customer_revenue
FROM customer_payment_summary;

结果:复杂的聚合逻辑在视图内部定义一次,之后您可以像处理常规数据集一样在多个单独的查询中使用它。


视图与常规表的区别

尽管视图通常看起来像表,但它们之间有重要区别。

1. 数据存储

  • 常规表 物理存储数据。
  • 视图 通常只存储 SQL 查询。

2. 结果来源

  • 常规表 包含自己的行。
  • 视图 显示从其他表或甚至其他视图获取的数据。

3. 数据新鲜度

  • 常规表 仅在 INSERTUPDATEDELETE 后更改。
  • 视图 通常在查询时显示底层表的当前状态。

4. 目的

  • 常规表 用于存储业务数据。
  • 视图 用于简化读取、重用和逻辑组织查询。

5. 数据修改

  • 常规表 直接用于插入、更新和删除行。
  • 视图 在某些情况下也可以支持数据修改,但这取决于特定的 DBMS 以及 VIEW 内部查询的复杂性。

视图特别有用的情况

如果满足以下条件,视图值得使用:

  • 相同的查询必须重复多次;
  • 您想要在更简单的名称后隐藏复杂的 JOIN、过滤器和聚合;
  • 您想要给用户或报告访问的不是完整的表,而只是所需的列和行;
  • 您想要使分析 SQL 更易于阅读和维护。

例如,您可以仅为昂贵的电影创建一个视图:

CREATE VIEW expensive_films AS
SELECT film_id, title, rental_rate, rating
FROM film
WHERE rental_rate >= 4.00;

SELECT title, rental_rate
FROM expensive_films
ORDER BY rental_rate DESC, title;

结果:主要的过滤逻辑保存在一个地方,因此在后续查询中您不需要每次都重复条件 WHERE rental_rate >= 4.00


视图与临时表

视图和临时表可以解决类似的任务,但它们之间有重要区别。

  • 临时表 通常存在有限的时间,并单独存储中间数据。
  • 视图 通常是永久的模式对象,仅存储查询。
  • 临时表 在需要物理保留中间结果的多个步骤中很方便。
  • 视图 在需要多次重用相同选择逻辑时很方便。
  • 临时表 更常用于数据处理工作流内部。
  • 视图 更常用作数据的方便命名访问层。

如果您需要一个必须单独存在并可能进一步处理的中间结果,临时表通常是更好的选择。如果您只需要一次定义现有数据的方便表示,VIEW 通常更合适。


您能通过视图修改数据吗

在许多 DBMS 中,简单视图不仅可以用于读取,还可以用于修改数据。例如,如果视图基于单个表,并且不包含复杂的聚合、GROUP BYDISTINCT 或多个表之间的连接,这可能是可行的。

例如,一个简单的视图可能如下所示:

CREATE VIEW active_customers_basic AS
SELECT customer_id, first_name, last_name, active
FROM customer
WHERE active = 1;

在某些 DBMS 中,您可以通过这样的视图运行 UPDATE。但您不应将此视为通用规则:视图逻辑越复杂,更新的可能性就越小。

在实践中,视图更常用于读取和简化查询。


注意事项

在使用视图时,记住以下几条规则是有益的:

  • 给视图起一个清晰的名称,反映其含义;
  • 如果使其难以阅读,不要在一个视图中隐藏太多逻辑;
  • 记住,针对视图的查询性能取决于视图内部的查询和底层表;
  • 不要自动假设任何视图都支持 INSERTUPDATEDELETE
  • 检查在特定任务中,普通 SELECT、CTE 或临时表是否更简单;
  • 考虑 DBMS 特定的功能,例如 CREATE OR REPLACE VIEW 或视图的可更新性规则。

设计良好的视图使 SQL 更简短、更清晰、更易于重用。


实际示例

想象一下,分析师定期需要一份电影及其类别名称的列表。您可以创建一个视图,而不是每次都写相同的 JOIN

CREATE VIEW film_category_details AS
SELECT f.film_id,
       f.title,
       f.rental_rate,
       c.name AS category_name
FROM film f
JOIN film_category fc ON f.film_id = fc.film_id
JOIN category c ON fc.category_id = c.category_id;

之后,任何查询变得更简单:

SELECT title, category_name, rental_rate
FROM film_category_details
WHERE category_name = 'Comedy'
ORDER BY rental_rate DESC, title;

SELECT category_name, COUNT(*) AS film_count
FROM film_category_details
GROUP BY category_name
ORDER BY film_count DESC;

这种方法很方便,因为复杂的表关系定义一次。之后,分析师、报告和应用程序可以使用现成的逻辑层,而无需不断重复相同的 JOIN 逻辑。


常见问题

视图存储数据还是仅存储查询?

在标准实现中,VIEW 仅存储 SQL 定义,而不是行的单独副本。当查询时,DBMS 从底层表构建结果。

何时选择视图而不是临时表?

当您需要多次重用相同的读取逻辑时,VIEW 更好。当您需要在多个处理步骤中物理持久化中间结果时,临时表更好。

视图能否自行提高性能?

不会自动。性能取决于 VIEW 内部的查询、源表的索引和执行计划。


面试问题

什么是 SQL 视图,它是如何工作的?

视图是一个命名的 SQL 查询,保存为模式对象。当您对其运行 SELECT 时,DBMS 执行存储的定义并返回一个虚拟表结果。

视图与常规表有什么不同?

常规表物理存储数据。视图通常仅存储查询逻辑,用于简化访问和重用复杂查询模式。

何时可以更新视图?

通常,当它是一个简单的视图,基于单个表且没有 GROUP BY、聚合、DISTINCT 或复杂连接时。确切规则取决于 DBMS。


本课的关键要点:

  • 视图 (VIEW) 存储的是 SQL 查询,而不是数据的单独副本。
  • 您可以像查询表一样查询视图,这简化了复杂逻辑的重用。
  • 视图特别适用于报告、分析以及隐藏复杂的 JOIN 和过滤器。
  • 与临时表不同,视图通常是永久的模式对象,不用于存储中间数据。
  • 并非所有视图都支持数据修改,这取决于特定的 DBMS 和查询结构。
  • 视图的性能取决于内部查询的编写效率。

在下一课中,我们将研究物化视图,并了解它们与常规视图的区别。

尝试解决以下任务,以巩固您在本课中学到的内容。

  1. 从数据库中删除视图
  2. 创建客户地址视图
  3. 企鹅平均值视图