请使用支持现代 CSS 与 JavaScript 的浏览器播放课件
DBPA · 3.6

视图

保存定义的虚表与数据窗口(不是数据副本)

VER. 2608.2 Built with impress.js

学习目标

视图保存查询定义,向用户提供可复用的数据窗口;它的查询和更新仍受来源关系与依赖约束

  1. 01区分基本表、视图和派生表的生命周期
  2. 02定义、查询并按依赖关系删除可复用的数据窗口
  3. 03解释显式列名与 WITH CHECK OPTION
  4. 04用视图消解说明查询如何在语义上改写回底层表,并区分物化结果
  5. 05判断哪些视图更新通常可以有意义地回写
  6. 06从四个角度评价视图的应用作用
2/19
LEARNING OBJECTIVES

视图可像表一样使用,但不保存数据副本

数据库主要保存视图定义,查询时再从来源关系得到当前结果

来源

视图可以引用一个或多个基本表或已有视图

存储

数据字典保存视图定义,而不是独立结果

使用

用户可以像查询基本表一样查询视图

3/19
VIRTUAL TABLE

视图与派生表的关键差异是生命周期

两者都由查询产生,但只有视图定义可以跨语句复用

对象定义保存生命周期
基本表表对象与数据字典持久存在
视图数据字典中的定义(不保存结果副本)持久存在
派生表当前 SQL 语句语句结束即消失
4/19
VIEW LIFECYCLE

CREATE VIEW:把 SELECT 定义为视图

视图列名要能清楚表达结果关系

基本表中的数据由视图定义形成一个按角色和任务使用的数据窗口
SQL
CREATE VIEW IS_Student
AS
SELECT Sno, Sname, Ssex, Sbirthdate, Smajor
FROM Student
WHERE Smajor = '信息管理与信息系统';
-- 目标列简单且名称唯一,因此可以省略列名列表
Takeaway

目标列名称唯一时可省略列名;表达式、聚集列或同名连接列需通过别名或显式列名列表命名;视图列名列表须全省略或全指定

5/19
CREATE VIEW

WITH CHECK OPTION:限制视图范围内的写入

通过视图写入的新行或新值仍必须满足视图定义中的条件

SQL
CREATE OR REPLACE VIEW IS_Student
AS
SELECT Sno, Sname, Ssex, Sbirthdate, Smajor
FROM Student
WHERE Smajor = '信息管理与信息系统'
WITH CHECK OPTION;

-- 越界 INSERT:会因 CHECK OPTION 被拒绝
INSERT INTO IS_Student (Sno, Sname, Ssex, Sbirthdate, Smajor)
VALUES ('20180011', '王伟', '男', '2003-11-01', '计算机科学与技术');

-- 越界 UPDATE:同样会被拒绝
UPDATE IS_Student
SET Smajor = '计算机科学与技术'
WHERE Sno = '20180005';
Takeaway

当前 MySQL 8.4 语境中,它重点约束 INSERT/UPDATE 产生的新行值;删除已经可见的行不是把它改到视图外,也不等同于权限机制

6/19
CHECK OPTION

不同视图表达不同的观察任务

连接、表达式和分组结果通常更难唯一回写

行列子集

单表筛选并保留主码;通常较易更新

连接视图

把多表关系封装成窗口;回写需看键与 DBMS

表达式视图

提供年龄等派生列;派生列不是底层事实列

分组视图

提供平均成绩等统计结果;通常没有唯一回写

7/19
VIEW TYPES

视图 SELECT 可封装连接、表达式与分组

视图保存来源查询的定义,用户仍按视图列名查询

SQL
-- 连接视图:列名按 SELECT 输出位置对应
CREATE VIEW IS_C1(Sno, Sname, Grade) AS
SELECT s.Sno, s.Sname, sc.Grade
FROM Student AS s JOIN SC AS sc ON s.Sno = sc.Sno
WHERE s.Smajor = '信息管理与信息系统'
  AND sc.Cno = '81001';

-- 表达式列:Sage 按年份差近似计算,显式命名
CREATE VIEW S_AGE(Sno, Sname, Sage) AS
SELECT Sno, Sname,
       EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM Sbirthdate)
FROM Student;

-- 聚集列也显式命名
CREATE VIEW S_GradeAVG(Sno, Gavg) AS
SELECT Sno, AVG(Grade) FROM SC GROUP BY Sno;

-- 嵌套视图:IS_C2 依赖 IS_C1
CREATE VIEW IS_C2(Sno, Sname, Grade) AS
SELECT Sno, Sname, Grade
FROM IS_C1
WHERE Grade >= 90;
Takeaway

查询视图时只需使用视图列名;列名列表按位置对应 SELECT 输出。是否能更新,要再看来源是否能唯一回写

8/19
VIEW DEFINITIONS

删除视图前要先检查依赖关系

视图对象可以被其他视图继续引用

SQL
-- 依赖链:IS_C2 引用 IS_C1;先盘点再清理
-- 直接删除 IS_C1 不能替代依赖检查
DROP VIEW IF EXISTS IS_C2;
DROP VIEW IF EXISTS IS_C1;

-- MySQL 8.4:RESTRICT/CASCADE 都会被解析但忽略
-- DROP VIEW IS_C1 CASCADE;
情况处理思路产品边界
没有下游依赖直接删除定义可用 IF EXISTS
存在下游视图先显式处理依赖再删除不把 CASCADE 当自动清理
MySQL 8.4 的 CASCADE参数被解析但忽略不执行标准式级联
基本表被删除视图可能失效定义清理需显式检查
9/19
DROP VIEW

查询视图沿用基本表的 SELECT 结构

用户只需表达视图范围内的业务条件

SQL
-- Smajor 条件来自视图;年龄条件是用户追加的“年份差近似”示例
SELECT Sno, Sbirthdate
FROM IS_Student
WHERE EXTRACT(YEAR FROM CURRENT_DATE)
    - EXTRACT(YEAR FROM Sbirthdate) <= 20;
Takeaway

视图隐藏了底层连接和筛选细节,但不改变结果语义

10/19
QUERY VIEW

视图消解:把查询改写到来源关系

视图消解不会生成或保存视图结果,也不规定唯一的物理执行顺序

检查

确认视图和来源对象存在

重写

组合视图定义的查询块、来源关系、投影列和用户条件;本例表现为条件合并

执行

交给 DBMS 选择执行计划;这不是固定执行顺序

11/19
VIEW RESOLUTION

行列子集视图的简单消解

行列子集视图通常可以把视图条件与用户条件合并,但其他视图可能需要不同的语义改写

SQL
-- 用户查询
SELECT Sno, Sbirthdate
FROM IS_Student
WHERE EXTRACT(YEAR FROM CURRENT_DATE)
    - EXTRACT(YEAR FROM Sbirthdate) <= 20;

-- 等价的基本表查询
SELECT Sno, Sbirthdate
FROM Student
WHERE Smajor = '信息管理与信息系统'
  AND EXTRACT(YEAR FROM CURRENT_DATE)
      - EXTRACT(YEAR FROM Sbirthdate) <= 20;
Takeaway

行列子集视图可以进行这种简单重写;连接、聚集或嵌套视图可能需要不同的查询改写

12/19
VIEW EXPANSION

聚集视图消解需要重组查询

视图外层的聚集条件应放在 HAVING,不能机械地放进 WHERE

SQL
-- 视图定义
CREATE VIEW S_GradeAVG(Sno, Gavg) AS
SELECT Sno, AVG(Grade)
FROM SC
GROUP BY Sno;

-- 用户查询
SELECT Sno, Gavg
FROM S_GradeAVG
WHERE Gavg >= 90;

-- 语义上的等价改写
SELECT Sno, AVG(Grade) AS Gavg
FROM SC
GROUP BY Sno
HAVING AVG(Grade) >= 90;
Takeaway

Gavg 是分组后的聚集结果,条件要落在 HAVING;该表达式展示查询重写,不是生成或保存一张物化结果表

13/19
AGGREGATE VIEW REWRITE

行列子集视图:写操作回写基本表

行列子集视图中的普通源列通常能定位底层元组;INSERT 还受列、约束和 CHECK OPTION 影响

SQL
UPDATE IS_Student
SET Sname = '刘新奇'
WHERE Sno = '20180005';

-- DELETE:删除视图中可见的底层元组
DELETE FROM IS_Student
WHERE Sno = '20180005';
Takeaway

UPDATE 和 DELETE 可以在逻辑上回写 Student;INSERT 还必须满足列、约束和 CHECK OPTION。视图不是隐藏的数据副本

14/19
UPDATE VIEW

不是所有视图都能被唯一地更新

视图能否更新取决于视图值是否唯一对应底层事实,以及操作、键和 DBMS 的支持范围

SQL
-- 一个平均值没有唯一的各科成绩回写方案
UPDATE S_GradeAVG
SET Gavg = 90
WHERE Sno = '20180001';
视图形态回写判断
行列子集通常可以唯一定位基本表元组
表达式/计算列派生值通常不能直接回写事实列
多表连接部分简单情形可能支持;须结合键、操作和 DBMS 判断
聚集与分组通常没有唯一的底层改法
Takeaway

理论上没有唯一回写语义,与某个 DBMS 暂不支持理论上可更新的写法是两回事;具体支持范围仍需查产品手册

15/19
UPDATE BOUNDARY

视图把同一数据组织成不同的工作窗口

视图通过抽象边界组织数据,而不是复制数据

安全保护

视图可以隐藏不应暴露的行和列,但实际权限仍需单独配置

有限逻辑独立

视图可以在一定范围内保持外模式稳定,但结构重构仍可能影响更新

简化操作

视图可以封装常用连接与筛选,用户可以直接查询 IS_C1

多角度访问

同一份基本数据可以为不同角色提供不同观察方式

16/19
VIEW BENEFITS

用定义、消解和回写边界理解视图

视图用保存的查询定义连接基本数据、用户和应用

定义

视图保存 SELECT 定义而不是结果副本,显式列名按位置对应 SELECT 输出

管理边界

WITH CHECK OPTION 约束视图范围内的写入,依赖视图需要显式清理

查询

简单视图可以进行语义重写,聚集视图的条件可能需要放在 HAVING

更新与作用

行列子集通常较易回写;安全、逻辑独立性、简化和多角度访问都受具体边界限制

Takeaway

视图可以为外模式提供有限稳定性、安全边界、简化查询和可理解的列结构;权限仍需单独配置

17/19
RECAP

本节知识地图

18/19
KNOWLEDGE MAP

本节问题

  1. 01何时必须为 CREATE VIEW 显式列名?列名能否只写一部分?
  2. 02IS_C2 依赖 IS_C1 时删除顺序如何?MySQL 8.4 如何处理 CASCADE
  3. 03WITH CHECK OPTION 会阻止哪些 INSERT/UPDATE?DELETE 可见行算不算越界?
  4. 04视图消解为何不是物化?S_GradeAVG 的条件为何写在 HAVING
  5. 05行列子集视图回写 INSERT/UPDATE/DELETE 各检查什么?聚集、表达式和复杂连接为何更难更新?
  6. 06视图如何支持安全、简化和多角度访问?为何逻辑独立性只是“一定程度”?
19/19
CHECK YOUR UNDERSTANDING