Skip to content

DB2 - 视图

本章将介绍视图(View),它是简化数据访问、增强安全性以及为数据库创建稳定 API 的强大工具。

视图是一个“虚拟表”,它基于存储的 SELECT 查询的结果集。视图本身不包含任何数据;它是一个命名的规范,当您查询它时,它会从一个或多个底层表中动态检索数据。

  • 简化性: 视图可以隐藏多表连接和复杂计算的复杂性,将数据以简单、单一的表形式呈现给最终用户或应用程序。
  • 安全性: 您可以创建一个视图,只暴露表中特定的列和行,从而向某些用户隐藏敏感数据。
  • 逻辑数据独立性: 您可以更改底层表的结构(例如,将一个表拆分为两个),但通过视图保持原始结构,从而避免重写应用程序代码。

使用 CREATE VIEW 语句。您可以在单个表上创建简单视图,也可以创建连接多个表的复杂视图。

-- 示例 1:一个用于安全性的简单视图
-- 隐藏 EMPLOYEES 表中的 salary 列
CREATE VIEW PUBLIC_EMPLOYEE_INFO AS
SELECT EMP_ID, FIRST_NAME, LAST_NAME, EMAIL, DEPARTMENT
FROM EMPLOYEES;
-- 示例 2:一个简化数据访问的复杂视图
-- 连接 orders 和 customers 表以显示包含客户姓名的订单详情
CREATE VIEW CUSTOMER_ORDERS AS
SELECT
O.ORDER_ID,
O.ORDER_DATE,
C.CUSTOMER_ID,
C.FIRST_NAME || ' ' || C.LAST_NAME AS CUSTOMER_NAME,
O.TOTAL_AMOUNT
FROM ORDERS O
JOIN CUSTOMERS C ON O.CUSTOMER_ID = C.CUSTOMER_ID;

您不能使用 ALTER VIEW 来更改底层 SELECT 语句。标准和推荐的做法是使用 CREATE OR REPLACE VIEW,它会在视图不存在时创建它,或者在视图存在时替换它。

-- 将配送地址添加到 CUSTOMER_ORDERS 视图
CREATE OR REPLACE VIEW CUSTOMER_ORDERS AS
SELECT
O.ORDER_ID,
O.ORDER_DATE,
C.CUSTOMER_ID,
C.FIRST_NAME || ' ' || C.LAST_NAME AS CUSTOMER_NAME,
C.SHIPPING_ADDRESS, -- 新增列
O.TOTAL_AMOUNT
FROM ORDERS O
JOIN CUSTOMERS C ON O.CUSTOMER_ID = C.CUSTOMER_ID;

要删除视图,请使用 DROP VIEW 语句。这不会影响底层表中的数据。

DROP VIEW PUBLIC_EMPLOYEE_INFO;

某些视图可以在 INSERT、UPDATE 或 DELETE 语句中使用,而另一些则严格为只读。

如果视图基于单个表且不包含会使目标行模糊的操作,则它通常是可更新的。如果视图的定义包含以下内容,则它变为只读的:

  • JOIN 操作
  • 聚合函数(SUM、COUNT 等)
  • GROUP BY 或 HAVING 子句
  • DISTINCT 关键字
  • 集合运算符(UNION、EXCEPT 等)

最佳实践: 为了清晰起见,通常最好将除最简单的视图之外的所有视图都视为只读,并直接在基表上或通过存储过程执行数据修改。

视图只是一个存储的查询;它本身并不能提高性能。针对视图的查询性能取决于其底层查询的性能。如果一个复杂的视图被频繁查询,其性能可能会成为瓶颈。

对于性能关键的场景,请考虑使用具体化查询表 (Materialized Query Table, MQT)。MQT 物理存储查询的结果集,作用类似于缓存表或汇总表。与视图相比,它提供了更快的读取访问速度,但代价是占用磁盘空间以及需要额外开销来保持 MQT 数据与基表同步。